The Observer design pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
A visualization of the classes and objects participating in this pattern.
The classes and objects participating in this pattern include:
Stock
)
IBM
)
IInvestor
)
Investor
)
This structural code demonstrates the Observer pattern in which registered objects are notified of and updated with a state change.
using System;
using System.Collections.Generic;
namespace Observer.Structural
{
/// <summary>
/// Observer Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
// Configure Observer pattern
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s, "X"));
s.Attach(new ConcreteObserver(s, "Y"));
s.Attach(new ConcreteObserver(s, "Z"));
// Change subject and notify observers
s.SubjectState = "ABC";
s.Notify();
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Subject' abstract class
/// </summary>
public abstract class Subject
{
private List<Observer> observers = new List<Observer>();
public void Attach(Observer observer)
{
observers.Add(observer);
}
public void Detach(Observer observer)
{
observers.Remove(observer);
}
public void Notify()
{
foreach (Observer o in observers)
{
o.Update();
}
}
}
/// <summary>
/// The 'ConcreteSubject' class
/// </summary>
public class ConcreteSubject : Subject
{
private string subjectState;
// Gets or sets subject state
public string SubjectState
{
get { return subjectState; }
set { subjectState = value; }
}
}
/// <summary>
/// The 'Observer' abstract class
/// </summary>
public abstract class Observer
{
public abstract void Update();
}
/// <summary>
/// The 'ConcreteObserver' class
/// </summary>
public class ConcreteObserver : Observer
{
private string name;
private string observerState;
private ConcreteSubject subject;
// Constructor
public ConcreteObserver(
ConcreteSubject subject, string name)
{
this.subject = subject;
this.name = name;
}
public override void Update()
{
observerState = subject.SubjectState;
Console.WriteLine("Observer {0}'s new state is {1}",
name, observerState);
}
// Gets or sets subject
public ConcreteSubject Subject
{
get { return subject; }
set { subject = value; }
}
}
}
This real-world code demonstrates the Observer pattern in which registered investors are notified every time a stock changes value.
using System;
using System.Collections.Generic;
namespace Observer.RealWorld
{
/// <summary>
/// Observer Design Pattern
/// </summary>
public class Program
{
public static void Main(string[] args)
{
// Create IBM stock and attach investors
IBM ibm = new IBM("IBM", 120.00);
ibm.Attach(new Investor("Sorros"));
ibm.Attach(new Investor("Berkshire"));
// Fluctuating prices will notify investors
ibm.Price = 120.10;
ibm.Price = 121.00;
ibm.Price = 120.50;
ibm.Price = 120.75;
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Subject' abstract class
/// </summary>
public abstract class Stock
{
private string symbol;
private double price;
private List<IInvestor> investors = new List<IInvestor>();
// Constructor
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);
}
Console.WriteLine("");
}
// Gets or sets the price
public double Price
{
get { return price; }
set
{
if (price != value)
{
price = value;
Notify();
}
}
}
// Gets the symbol
public string Symbol
{
get { return symbol; }
}
}
/// <summary>
/// The 'ConcreteSubject' class
/// </summary>
public class IBM : Stock
{
// Constructor
public IBM(string symbol, double price)
: base(symbol, price)
{
}
}
/// <summary>
/// The 'Observer' interface
/// </summary>
public interface IInvestor
{
void Update(Stock stock);
}
/// <summary>
/// The 'ConcreteObserver' class
/// </summary>
public class Investor : IInvestor
{
private string name;
private Stock stock;
// Constructor
public Investor(string name)
{
this.name = name;
}
public void Update(Stock stock)
{
Console.WriteLine("Notified {0} of {1}'s " +
"change to {2:C}", name, stock.Symbol, stock.Price);
}
// Gets or sets the stock
public Stock Stock
{
get { return stock; }
set { stock = value; }
}
}
}
The .NET optimized code demonstrates the
same real-world situation as above but uses modern, built-in .NET features,
such as, generics, reflection, LINQ, lambda functions, etc.
You can find an example on our Singleton pattern page.
All other patterns (and much more) are available in our Dofactory .NET product.
Not only does Dofactory .NET cover the Gang of Four and Enterprise patterns, it also includes
pattern architectures, low-code, and RAD (Rapid Application Development) techniques.
Accelerate development to where you can write
entire solutions in just 33 days!.
This unique package will change your developer lifestyle.
Here's what is included: