// November 2nd, 2006 // No Comments » // .net, Algorithms, Language Idioms, design patterns, software development
Two months ago, I posted about how to Communicate between C# classes, which actually displays an Observer pattern in a C# way, using delegates and events. After finishing my post, I felt like something was missing, so this is my attempt to fill in the blanks.
The Observer Pattern
Also know as the Publisher/Subscriber pattern is generally used to monitor the state of an instance or object in an application. The idea behind the Observer pattern is to communicate the state of one class instance to another, in another words communicating between each other (at least unidirectionally).
There are several implementations for this pattern, especially for C#. Even thought the Observer pattern is implemented implicitly in C# with delegates and events, I’m going to display other two solutions which I consider interesting.
The Observer pattern has two actors involved, the Subject (which is going to be observed) and the Observer. There’s actually no way that I know of which doesn’t impose a penalty on performance, where the Observer is actually monitoring the Subject. this pattern refers only to the Subject notifying the Observers his own changes, considering of course that the Subject does know about any changes it may have.
So the idea resides on the fact that the Subject notifies its observes about any changes there may be. If there are any changes, once the Observer is notified, it can decide to something with the message or just discard it.
The idea of course of an Observer is something that observes without the Subject being notified, but in this case is different. That is why people always get confused with the Observer pattern, most of them believe that the Observer obtains information from the Subject without the it knowing. Which can actually be really useful. But this is not the case. In this case the Subject notifies the Observer (So maybe it should be call the Notification pattern).
Anyways, this pattern can be used for many different situations, and I don’t intend to cover all of them, it is actually impossible. But this pattern is used a lot in Event Listeners and Event handlers throughout Frameworks, especially Java and C#.
When a button in a form is clicked, then an event is fired, and the event handlers or listeners handle event.In this case the Subject is represented by the Form button which is part of the View in an MVC pattern, and the Observer is the actual controller. Most frameworks now, have the View and Controller in the same class so this would not count as unilateral object communication. But in my previous post it is.
Let’s think about this for a moment. We have a Form which contains a ProgressBar, and the progress value represents the progress of a very long process that is in the Model of the application. Let’s call the Form Myform; and the Model MyModel. So MyModel is doing a very long process, and it notifies MyForm of the progress each time it advances.
This would make MyModel the Subject and MyForm the Observer. MyForm is being notified for all changes in progress made by MyModel. There can be several types of notifications or events; in this case, the notification is related to the progress of MyModel, but then MyModel could also notify all Observers about the estimated ending time of the lengthy process.
Let’s look at some Implementations:
· Highly Coupled Implementation
This implementation is the simplest of all, and it only responds to the pattern policy, not taking into consideration the coupling between classes.
First we have the Observer Interface:
using System;
namespace ObserverPattern
{
/// <summary>
/// Interface that represents the observer in the Observer pattern.
/// </summary>
public interface IObserver
{
/// <summary>
/// Triggers an update in the observer class.
/// </summary>
/// <param name="subject">Object reference of the subject updating.</param>
void Update(Subject subject);
}
}
As you can see in the code, the interface for all observers has a method that is called update. This method is called when the Subject object has notified its Observers.
Next we examine the Subject implementation:
using System;
using System.Collections;
namespace ObserverPattern
{
/// <summary>
/// Class that represents the abstract subject of an observer pattern.
/// </summary>
public abstract class Subject
{
/// <summary>
/// List of registered observers.
/// </summary>
private ArrayList observers = new ArrayList();
/// <summary>
/// Default Constructor.
/// </summary>
public Subject()
{
}
/// <summary>
/// Adds an observer to the list of registered observers
/// </summary>
/// <param name="observer">Observer to add</param>
public void AddObserver(IObserver observer)
{
observers.Add(observer);
}
/// <summary>
/// Removes an observer to the list of registered observers.
/// </summary>
/// <param name="observer">Observer to remove</param>
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer);
}
/// <summary>
/// Notifies all registered observers.
/// </summary>
public void Notify()
{
foreach(IObserver observer in observers) {
observer.Update(this);
}
}
}
}
As you it can be seen in the code, this abstract class is a little more complex than the observer interface. The Subject is based on a list of Observers which can be added or removed from the list, and which are notified as required. The method Notify() is the one that communicates with the observes through their Update() method.
Since the Subject class is abstract, it cannot be instantiated, it can only be inherited, so we need an implementation class for the Subject, let’s call it MySbuject:
using System;
using System.Collections;
namespace ObserverPattern
{
/// <summary>
/// Class that represents the subject of an observer pattern.
/// </summary>
public abstract class MySubject : Subject
{
/// <summary>
/// Default Constructor.
/// </summary>
public MySubject() : base()
{
}
/// <summary>
/// Notifies all observers.
/// </summary>
public void NotifyObservers()
{
this.Notify(this);
}
}
}
MySbuject is a simple class which implements the Subject abstract class, and which notifies all Observers through the NotifyObservers() method.
Now let’s look at the MyObserver implementation of IObserver:
using System;
namespace ObserverPattern
{
/// <summary>
/// Class that represents the observer in the Observer pattern.
/// </summary>
public class MyObserver : IObserver
{
/// <summary>
/// Triggers an update in the observer class.
/// </summary>
/// <param name="subject">Object reference of the subject updating.</param>
public void Update(Subject subject)
{
// Do some work.....
}
}
}
The updateMethod() is the one that actually handles the notification from the Subject, and here it decides whether to do something with the notification or just discard it; that all depends on the notification or event type.
Advantages
The Advantages of this implementation is that is very simple to grasp. It has no other complexities than that of the pattern itself.
Disadvantages
This implementation has a lot of disadvantages; first of all it has a really tight coupling between the classes, especially the Subject abstract class and MySubject class. I have never been a supporter of Inheritance. I know it is some times useful, even though I can’t think of one now, but I still prefer composition, or interfaces.
Another disadvantage is that the implementation is lengthy. There are at least 4 classes involved, which I consider not to be simple enough.
· Less Coupled Implementation
Let’s tackle on disadvantage at a time. Let’s decouple the classes a little bit.
Since the Subject abstract class contains implementation for the methods Add, Remove and Notify; and they are all implemented in the same way for all Subjects, there is no need to implement the process of Adding, Removing and Notifying observers in all childs classes by building an implementation. Let’s use Interfaces and Composition.
In order to do this, we need to create an interface for all Subjects which we will call ISubject:
using System;
using System.Collections;
namespace ObserverPattern
{
/// <summary>
/// Interface that represents the subject of an observer pattern.
/// </summary>
public interface ISubject
{
/// <summary>
/// Adds an observer to the list of registered observers
/// </summary>
/// <param name="observer">Observer to add</param>
void Add(IObserver observer);
/// <summary>
/// Removes an observer to the list of registered observers.
/// </summary>
/// <param name="observer">Observer to remove</param>
void Remove(IObserver observer);
/// <summary>
/// Notifies all registered observers.
/// </summary>
void Notify();
}
}
The interface, as it can be seen in the code, only contains the methods that were mentioned in the Subject abstract class but without implementation. this interface helps decouple the IObserver interface too, and it would change in the following way:
using System;
namespace ObserverPattern
{
/// <summary>
/// Interface that represents the observer in the Observer pattern.
/// </summary>
public interface IObserver
{
/// <summary>
/// Triggers an update in the observer class.
/// </summary>
/// <param name="subject">Object reference of the subject updating.</param>
void Update(ISubject subject);
}
}
As you can see in the code, now the IObserver interface uses ISubject interface instead of an Subject abstract class, which made it dependent on the implementation of the Subject; now the interface is free from implementation.
Now we have a problem. If all subject implement this interface (ISubject), they are all going to re-invent the wheel while implementing Add, Remove and Notify methods for all Subjects. We can actually fix this with composition.
Let’s create a new class named SubjectHelper, which has the following implementation:
using System;
using System.Collections;
namespace ObserverPattern
{
/// <summary>
/// Class that represents the subject helper of an observer pattern.
/// </summary>
/// <remarks>
/// This class is created to lesser the coupling between the IObserver interface
/// and the abstract Subject class. Splitting the Subject abstract class into an
/// ISubject interface and a SubjectHelper class.
/// Then the helper is only a provider of notification services, which any class
/// can use without creating tightly coupled classes.
/// </remarks>
public class SubjectHelper : ISubject
{
/// <summary>
/// List of registered observers.
/// </summary>
private ArrayList observers = new ArrayList();
/// <summary>
/// Default Constructor.
/// </summary>
public SubjectHelper()
{
}
/// <summary>
/// Adds an observer to the list of registered observers
/// </summary>
/// <param name="observer">Observer to add</param>
public void Add(IObserver observer)
{
observers.Add(observer);
}
/// <summary>
/// Removes an observer to the list of registered observers.
/// </summary>
/// <param name="observer">Observer to remove</param>
public void Remove(IObserver observer)
{
observers.Remove(observer);
}
/// <summary>
/// Notifies all registered observers.
/// </summary>
/// <param name="realSubject">Real subject calling the helper.</param>
public void Notify(object realSubject)
{
foreach(IObserver observer in observers) {
observer.Update(realSubject);
}
}
}
}
As you can see, the SubjectHelper class includes all the implementation for the methods Add, remove and Notify, just like it used to in the Subject abstract class. It is the same implementation, except for the Notify method, which includes a parameter for the real subject, or the real sender.
Let me show you how the SubjectHelper would be used, in the implementation of MySubject class:
using System;
using System.Collections;
namespace ObserverPattern
{
/// <summary>
/// Class that represents the subject of an observer pattern.
/// </summary>
public abstract class MySubject
{
private SubjectHelper subjectHelper = new SubjectHelper();
/// <summary>
/// Default Constructor.
/// </summary>
public MySubject() : base()
{
}
/// <summary>
/// Adds an observer to the list of registered observers
/// </summary>
/// <param name="observer">Observer to add</param>
public void AddObserver(IObserver observer)
{
this.subjectHelper.Add(observer);
}
/// <summary>
/// Removes an observer to the list of registered observers.
/// </summary>
/// <param name="observer">Observer to remove</param>
public void RemoveObserver(IObserver observer)
{
this.subjectHelper.Remove(observer);
}
/// <summary>
/// Notifies all observers.
/// </summary>
public void NotifyObservers()
{
this.subjectHelper.Notify(this);
}
}
}
Composition is a really great design artifact. the idea behind the MySubject class is that it DOESN’T inherit ISubject interface, but it wraps around the SubjectHelper; leaving out all problems related to inheritance. This is what composition is all about.
Advantages
This approach reduces the coupling enough to be a flexible solution. It can be reused without any problems of scalability.
Disadvantages
It is a bit more complex than the other approach, and it is a lot bigger in number of classes. The other approach had 4 classes involved, this approach has 5.
· .Net Implementation
C# is a piece of beauty. The less coupled approach is a great implementation, don’t get me wrong, but it is still a lot of code. Well don’t worry, for C# we have a concept called ‘Delegates’ which simplifies the Observer pattern a lot.
Let’s see the implementation of the observer pattern using Delegates, shown below is the Subject’s implementation:
using System;
namespace DotNetObserverPattern
{
/// <summary>
/// Class that represents a subject in the observer pattern.
/// </summary>
public class MySubject
{
/// <summary>
/// Delegate that represents a notify handler.
/// </summary>
public delegate void NotifyHandler(object Subject);
/// <summary>
/// Notify Event Handler.
/// </summary>
public event NotifyHandler NotifyEvent;
/// <summary>
/// Default Constructor.
/// </summary>
public MySubject()
{
}
/// <summary>
/// Notifies all registered observers.
/// </summary>
public void Notify()
{
if(null != NotifyEvent) {
this.NotifyEvent(this);
}
}
}
}
As you can see there is no need for an interface ISubject or a SubjectHelper. Everything is already done with the delegates publish/subscribe mechanism. It is simply a piece of beauty.
Now let’s see the Observer implementation:
using System;
namespace DotNetObserverPattern
{
/// <summary>
/// Class that represents an observer in the observer pattern.
/// </summary>
public class MyObserver
{
/// <summary>
/// Default Constructor.
/// </summary>
public MyObserver()
{
}
/// <summary>
/// Triggers an update in the observer class.
/// </summary>
/// <param name="subject">Object reference of the subject updating.</param>
public void Update(Object subject)
{
if(subject is MySubject) {
// Do some work....
}
}
}
}
Also very simple.
Advantages
It is very simple. It is not tightly coupled. It just takes a few lines of code.
Disadvantages
None that I could think of at the time of witting this post.
· Conclusion
The three implementations work and they follow the Observer pattern policy. Each one has its advantages and disadvantages. I obviously use the .Net implementation, since it is a lot simpler and more robust.
Tweet This Post