Home > Patterns and Practices > Observer Pattern

Observer Pattern

Observer Pattern

Problem:

How can an object notify other objects of state changes without being dependent on their classes? Some explanation is required on this statement, isn’t it? In a retail store when the stock of a product reaches zero quantity, it is called a sellout. Assume we have a Stock class which maintains the stock quantity for the product. When the quantity reaches zero a sellout occurs. The store displays the sellouts in a Dashboard for the store personnel to replenish the product from the backstage to sale areas. The state change (quantity of a product falling to zero) has to be notified to the Dashboard. Assume we have the Stock class having a reference to the Dashboard class and notifies it on a Sellout.

 

Let us say that the store wants to display the Sellouts on best selling products on to a separate TopSeller Dashboard which is monitored by the store manager. Now we need to modify the Stock class to have a TopSellerDashboard class reference too. This clearly violates our good old friend, OCP. Also the reuse of the stock class becomes difficult because of the dependencies. How do remove this tight coupling is the intent of Observer pattern.

 

Solution:

Basic Observer structure

 

The solution presented in the above figure shows the ConcreteSubject class inheriting from the Subject class. The Subject class contains the implementations of the methods to add or remove observers and to iterate through the list of observers. All ConcreteSubject has to do is to inherit from Subject and call Notify() when a state change occurs. In languages that only support single inheritance (such as Java or C#), inheriting from Subject precludes the class from inheriting from any other class. This can be a problem because in many cases ConcreteSubject is a domain object that may inherit from a domain object base class. Therefore, it is a better idea to replace the Subject class with a Subject interface and to provide a helper class for the implementation.

Unfortunately, you now have to add code to each class that inherits from the Subject interface to implement the methods defined in the interface. This task can become very repetitious. Also, because the domain object coincides with ConcreteSubject, it cannot differentiate between different types of state changes that would be associated with different subjects. This only allows observers to subscribe to all state changes of ConcreteSubject, even though you may want to be more selective (for example, if the source object contains a list, you may want to be notified of updates, but not of insertions). You could have the observers filter out notifications that are not relevant, but that makes the solution less efficient, because ConcreteSubject calls all the observers just to find out that they are really not interested.

You can resolve these issues by separating the subject completely from the source class (see figure below). Doing so reduces ConcreteSubject to the implementation of the Subject interface; it has no other responsibilities. This allows DomainObject to be associated with more than one ConcreteSubject so that you can differentiate between different types of events for a single domain class.

The event and delegate features in the .NET Framework implement this approach as a language construct so that you do not even have to implement your own ConcreteSubject classes anymore. Basically, events replace the ConcreteSubject classes, and delegates implement the role of the Observer interface. This article uses illustrations and text from the Microsoft P&P Guide to explain the observer pattern.

 

For the stock example the Domain object is the Stock object and the SelloutOccurred event is the Concrete Subject. The SelloutOccurredEventHandler delegate is the observer interface and the Dashboard and the TopSellerDashboard classes which provide the SelloutOccurredEventHandler delegate are the concrete observers.

Advertisements
  1. No comments yet.
  1. November 19, 2010 at 11:00 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: