[home] [blog] [services] [portfolio] [contact]
Print Shortlink

Design Patterns: Observer

A very common design pattern is the Observer pattern. Where do we see Observer patterns in our code? Events and delegates. Essentially Events are a slightly modified version of a delegate, and delegates are an implementation of the observer pattern. An interesting article on this is available here if you are interested.

A simplified example of the Observer pattern can be seen below. This example shows how “subscribers” can be attached to a stock price and receive notifications when they change. In a real-world example we would accomplish this using events, or our send out notifications via network transmission instead of outputting to the screen.


class ObserverPattern
	{
		// Participants:
		// Subject
		// Observer
		// ConcreteSubject (optional)
		// ConcreteObserver (optional)

		public ObserverPattern()
		{
			IBM ibm = new IBM(120);
			ibm.Attach(new Investor("John Doe"));
			ibm.Attach(new Investor("Jane Doe"));

			// ok create a few fluctuating prices
			ibm.Price = 130;
			ibm.Price = 132;
			ibm.Price = 132.5;

		}
		
	}

	/// <summary>
	/// The Subject abstract class, as a Stock symbol
	/// </summary>
	public abstract class Stock
	{
		private string symbol;
		private double price;
		private List<IInvestor> investors = new List<IInvestor>();

		public double Price
		{
			get { return price; }
			set {
				// If the price has changed, notify the subscribers
				if (price != value)
				{
					price = value;
					Notify();
				}
			}
		}

		public string Symbol
		{
			get { return symbol; }
		}

		public Stock(string symbol, double price)
		{
			this.symbol = symbol;
			this.price = price;
		}

		public void Attach(IInvestor investor)
		{
			investors.Add(investor);
		}

		public void Detach(IInvestor investor)
		{
			investors.Remove(investor);
		}

		public void Notify()
		{
			foreach (IInvestor investor in investors)
			{
				investor.Update(this);
			}
		}
	}

	/// <summary>
	/// The ConcreteSubject class, as a specific Stock symbol
	/// </summary>
	public class IBM : Stock
	{
		public IBM(double price) : base("IBM", price) { }
	}

	public class Investor : IInvestor
	{
		private string name;
		private Stock stock;

		public Stock Stock
		{
			get { return stock; }
			set { stock = value; }
		}

		public Investor(string name)
		{
			this.name = name;
		}

		public void Update(Stock stock)
		{
			Console.WriteLine("To {0}: {1} changed to {2:C}", name, stock.Symbol, stock.Price);	
		}
	}

	/// <summary>
	/// The Observer interface/abstract class
	/// </summary>
	public interface IInvestor
	{
		void Update(Stock stock);
	}

Leave a Reply


4 × eight =