RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Design Patterns for ASP.NET Developers, Part 3: Advanced Patterns  : Page 4

Find out how to use Factory, Builder, and Injection Patterns in ASP.NET to construct different representations of complex objects.

A Combined Command-Observer Pattern
A modified version of the Observer pattern can provide most of the features of the Command and the Publish-Subscribe patterns in ASP.NET. It provides for separation of the Observer and the Subject by using an interface that defines the requirements of each Observer—in much the same way as an EventHandler class defines the nature of an event in the Publish-Subscribe pattern that a subscriber can handle. A Helper class, referenced through the Subject, maintains a list of Observers and can call the appropriate method on each one when a specified action takes place on the Subject.

In this implementation, the client or application code creates instances of the Observer objects that it wants the Subject to notify when an action occurs. For example, in the sample application, the code creates instances of a PartsDept, a TransportDept, and a SalesDept as Observer objects. It then subscribes these objects to a Helper class that maintains an internal list of subscribed Observers (see Figure 4).

Figure 4. Subscription in the Command-Observer Implementation: The figure shows how an application creates Observer object instances that subscribe to messages from the Subject class through a helper class that maintains a list of subscribed Observers.
Figure 5. Notification in the Command-Observer Implementation: The diagram shows the sequence of events when a client calls a method on the Subject that raises events to which various Observer instances have subscribed.
The client application then calls a method on the ProductionLine class (the Subject)—an instance of which it has previously created. The ProductionLine class holds a reference to the Helper class, and calls its Notify method. The Helper class then calls the Update method on each subscribed Observer instance (see Figure 5).

Effectively, this provides a technique where the client can add commands (Observers) to a Subject without the Subject being previously aware of the nature of the target—as long as that target implements the Observer interface. At minimum, the Observer interface must expose an Update event that the Helper class can call. Depending on the nature of the implementation and requirements, the interface can specify the parameters to pass to the Observer and other methods or properties that it must expose.

Implementation of the Command-Observer Pattern
The example application demonstrates the Command-Observer pattern with an application that looks and behaves exactly the same way as the Publish-Subscribe pattern implementation shown earlier in this article. The difference is in the way that the classes interact when the publisher/subject sends notifications to each subscriber/observer instance.

To provide independence between the observer and subject, each Observer implements an interface named IObserver. This allows classes to reference observer instances using the interface definition rather than the actual class type of the observer. Alternatively, you could create a base class that contains common observer functionality, and use that rather than an interface definition.

In this simple example, the IObserver interface defines only a single method, named Update, which each observer must implement. The subject calls this method through its helper class to notify each observer whenever it builds a new car:

   public interface IObserver
     // observed objects must provide a method 
     // that updates its content or performs the
     // appropriate actions
     void Update(Object subject);
As in the Publish-Subscribe example, the Command-Observer implementation uses a helper class to raise the notification to all observers. This class, named ObserverHelper, maintains an internal ArrayList that contains references to each subscribed observer. The class exposes methods for adding or removing observers from the list, using the IObserver interface to maintain independence between concrete classes.

The ObserverHelper class also exposes the Notify method, which the subject calls to notify all observers when the relevant action occurs in the subject class. The Notify method simply iterates through the list of subscribed observers, calling the Update method on each one, passing a reference to the subject (which is passed into the Notify method as a parameter):

   public class ObserverHelper
     private ArrayList observerList = new ArrayList();
     public void AddObserver(IObserver observer)
     // subscribe an observer by adding them to the list
     public void RemoveObserver(IObserver observer)
     // unsubscribe an observer by removing them from the list
     public void Notify(Object subject)
     // notify all subscribed observers
       foreach(IObserver observer in observerList)
         // call update method on all subscribed observers
The subject class, named ProductionLine in this example, carries out the main tasks of the application. It maintains a reference to an associated ObserverHelper instance created in its constructor and exposed through the ObserverHelper property—in the same way the previous Publish-Subscribe example exposed its BuildCarHelper class:

   public class ProductionLine
     // holds a reference to an instance of the helper 
     // class that handles subscriptions and notifies all the 
     // subscribed observers
     private ObserverHelper internalHelper = null;
     // name of car currently being built
     private String carName = String.Empty;
     // class constructor
     public ProductionLine(String motorCarName)
       // get new help class instance
       internalHelper = new ObserverHelper();
     // property that exposes the helper instance
     public ObserverHelper Helper
       get { return internalHelper; }
In addition, like the Publish-Subscribe example, the ProductionLine class in this example exposes the name of the car it is currently building as a property, and a method named BuildNewMotorCar that saves the car model name in the local variable and calls the Notify method of its associated helper class:

     // any properties required to expose data that the 
     // observers may need to use. Actual properties depend on 
     // actions of subject and observer, but using properties 
     // maintains interface independence
     public String CurrentMotorCarName
       get { return carName; }
     // main method for class - this is called by the client 
     // to carry out the main tasks. Can expose more methods, 
     // but each must call the Notify method of the associated 
     // helper instance
     public void BuildNewMotorCar(String motorCarName)
       // save value of car name
       carName = motorCarName;
       // do whatever work required here
       // ...
       // notify all subscribed observers

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date