Introduction
This article presents the basics of Observer Pattern, when to use it and how to implement it in C#.
Background
Many a times, we need one part of our application updated with the status of some other part of the application. One way to do this is to have the receiver part repeatedly check the sender for updates, but this approach has two main problems. First, it takes up a lot of CPU time to check the new status and second, depending on the interval we are checking for change we might not get the updates "immediately".
This problem has one easy solution i.e. Observer Pattern. I know many guys will shoot me in the neck on reading this article because this perhaps is going to be 100th article on CodeProject alone but still I think it is worth sharing it, as it could be useful for the beginners and also the valuable comments I get on the article will let me learn more.
Here is the Class diagram for the Observer pattern (Reference: GoF Design Patterns)
Using the Code
Let us now discuss all the classes one by one:
Subject
: This class keeps a track of all the observers and provides the facility to add or remove the observers. Also it is the class that is responsible for updating the observers when any change occurs. In our solution, we have ASubject
implemented for the same purpose. ConcreteSubject
: This class is the real class that implements the Subject
. This class is the entity whose change will affect other objects. We have DummyProject
class implemented for the same. Observer
: This represents an interface that defines the method that should be called whenever there is change. We have implemented this as IObserver
. ConcreteObserver
: This is the class which needs to keep itself updated with the change. This class just needs to implement the Observer
and register itself with the ConcreteSubject
and it is all set to receive the updates. We have Shop
class in our application serving the same purpose.
So let me just have the same diagram I've shown above for my implementation here:
Before we go ahead and see the code, there is one more thing I want to say here. In .NET, we have delegates which are actually a very good example of Observer pattern. So actually we don't need to implement the pattern completely in C# as we can use the delegates for the same functionality, but we have done it here for understanding the pattern. Also, we have implemented the delegate's way of having an observer pattern working too. So let's now look at the code.
The Subject: ASubject
abstract class ASubject
{
ArrayList list = new ArrayList();
public delegate void StatusUpdate(float price);
public event StatusUpdate OnStatusUpdate = null;
public void Attach(Shop product)
{
list.Add(product);
}
public void Detach(Shop product)
{
list.Remove(product);
}
public void Attach2(Shop product)
{
OnStatusUpdate += new StatusUpdate(product.Update);
}
public void Detach2(Shop product)
{
OnStatusUpdate -= new StatusUpdate(product.Update);
}
public void Notify(float price)
{
foreach (Shop p in list)
{
p.Update(price);
}
if (OnStatusUpdate != null)
{
OnStatusUpdate(price);
}
}
}
The ConcreteSubject: DummyProduct
class DummyProduct : ASubject
{
public void ChangePrice(float price)
{
Notify(price);
}
}
The Observer: IObserver
interface IObserver
{
void Update(float price);
}
The ConcreteObserver: Shop
class Shop : IObserver
{
string name;
float price = 0.0f;
public Shop(string name)
{
this.name = name;
}
#region IObserver Members
public void Update(float price)
{
this.price = price;
Console.WriteLine(@"Price at {0} is now {1}", name, price);
}
#endregion
}
Testing the Code
static void Main(string[] args)
{
DummyProduct product = new DummyProduct();
Shop shop1 = new Shop("Shop 1");
Shop shop2 = new Shop("Shop 2");
Shop shop3 = new Shop("Shop 3");
Shop shop4 = new Shop("Shop 4");
product.Attach(shop1);
product.Attach(shop2);
product.Attach2(shop3);
product.Attach2(shop4);
product.ChangePrice(23.0f);
product.Detach(shop2);
product.Detach2(shop4);
product.ChangePrice(26.0f);
Console.Read();
}
Points of Interest
The heart of Windows Forms programming and MPF Applications is the Observer Pattern. Since the event driven mechanism can only be facilitated by implementing the Observer pattern, I wrote a very basic and perhaps "not-so-useful-to-others-who-know-stuff" article, but I did enjoy learning and writing it. Now the next step for me is to implement the same in C++ (with pointers, vectors, iterators and other good stuff).
History
- 10 February, 2012: Simple and rudimentary implementation of Observer pattern in C#