The Observer pattern is intended to provide you with a means to present data in several different forms at once so that when one object changes state, all its dependents are notified and updated automatically.
The Observer pattern can be found everywhere. Mostly it is used when you have more than one view on the same data. For example, a list view and a detail view.
In the client, a couple of observers are attached to their subject of interest. As soon as the state of the subject changes, all observers are notified that there is a change of state.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Client { static void Main() { ConcreteSubject subject = new ConcreteSubject(); ConcreteObserver observer1 = new ConcreteObserver(subject, "A"); subject.Attach(observer1); ConcreteObserver observer2 = new ConcreteObserver(subject, "B"); subject.Attach(observer2); subject.SubjectState = "NEW_SUBJECT_STATE"; subject.Notify(); Console.ReadKey(); } } |
The abstract parent class Subject contains a list of observers and methods necessary for attaching and detaching observers. Most important method is notify which traverses the list and notifies all attached observers.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
abstract class Subject { private List m_Observers = new List(); public void Attach(Observer observer) { m_Observers.Add(observer); } public void Detach(Observer observer) { m_Observers.Remove(observer); } public void Notify() { foreach (Observer o in m_Observers) { o.Update(); } } } |
The concrete child class contains a certain state, which can be virtually anything. In this example, something simple. Just a string containing im-por-tant information.
|
1 2 3 4 |
class ConcreteSubject : Subject { public string SubjectState { get; set; } } |
All observers need some way to update their state when they are notified. This is done by implementing the Update method of abstract class Observer.
|
1 2 3 4 |
abstract class Observer { public abstract void Update(); } |
The concrete observer implements the abstract update method, plus its own methods.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class ConcreteObserver : Observer { private string m_Name; private string m_ObserverState; public ConcreteObserver(ConcreteSubject subject, string name) { this.Subject = subject; this.m_Name = name; } public override void Update() { m_ObserverState = Subject.SubjectState; Console.WriteLine("Observer {0}'s new state is {1}", m_Name, m_ObserverState); } public ConcreteSubject Subject { get; set; } } |
When you think about the problem this pattern solves, you probably agree with me that this is a relatively simple but powerful pattern.
This post is part of a series on the foundational design patterns in C#. In this series we explore the ancient design patterns and their use in real-world programming situations of today. In these series of posts we explore each pattern by looking at a minimalistic example to reveal its structure and then look at more concrete and useful real-world C# code that implements the pattern.
Comments