Observer Design Patttern
By Peter Bromberg
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated
automatically.
The Observer design pattern is one of two Gang-of-Four design patterns (the other is the Iterator pattern) that have found their way, not only into the .NET Framework libraries, but also in the .NET languages themselves. When programming a Web application or a Windows application you often work with events and event handlers.
using System;
using System.Collections.Generic;
namespace DoFactory.GangOfFour.Observer.NETOptimized
{
class MainApp
{
static void Main()
{
// Create IBM stock and attach investors
IBM
ibm = new IBM(120.00);
// Attach 'listeners', i.e. Investors
ibm.Attach(new Investor { Name = "Sorros" });
ibm.Attach(new Investor { Name = "Berkshire" });
// Fluctuating prices will notify listening investors
ibm.Price
= 120.10;
ibm.Price
= 121.00;
ibm.Price
= 120.50;
ibm.Price
= 120.75;
// Wait for user
Console.ReadKey();
}
}
// Custom event arguments
public class ChangeEventArgs : EventArgs
{
// Gets or sets symbol
public string Symbol { get; set; }
// Gets or sets price
public double Price { get; set; }
}
/// <summary>
/// The 'Subject' abstract class
/// </summary>
abstract class Stock
{
protected string _symbol;
protected double _price;
// Constructor
public Stock(string symbol, double price)
{
this._symbol = symbol;
this._price = price;
}
// Event
public event EventHandler<ChangeEventArgs> Change;
// Invoke the Change event
public virtual void OnChange(ChangeEventArgs e)
{
if (Change != null)
{
Change(this, e);
}
}
public void Attach(IInvestor investor)
{
Change += investor.Update;
}
public void Detach(IInvestor investor)
{
Change -= investor.Update;
}
// Gets or sets the price
public double Price
{
get
{ return _price; }
set
{
if (_price != value)
{
_price
= value;
OnChange(new ChangeEventArgs { Symbol = _symbol, Price = _price });
Console.WriteLine("");
}
}
}
}
/// <summary>
/// The 'ConcreteSubject' class
/// </summary>
class IBM : Stock
{
// Constructor - symbol for IBM is always same
public IBM(double price)
:
base("IBM", price)
{
}
}
/// <summary>
/// The 'Observer' interface
/// </summary>
interface IInvestor
{
void Update(object sender, ChangeEventArgs e);
}
/// <summary>
/// The 'ConcreteObserver' class
/// </summary>
class Investor : IInvestor
{
// Gets or sets the investor name
public string Name { get; set; }
// Gets or sets the stock
public Stock Stock { get; set; }
public void Update(object sender, ChangeEventArgs e)
{
Console.WriteLine("Notified {0} of {1}'s " +
"change to {2:C}", Name, e.Symbol, e.Price);
}
}
}
Observer Design Patttern (465 Views)