Thursday, February 16, 2012

Design Pattern : Observer Pattern Implementation

The observer design pattern defines a one to many dependency between 
an object and its dependents. The dependency is created in order to inform
the dependents that the object changed its state and therefore the dependents
can react to the change. A very good example of such behavior is the blogging
systems were subscribers are notified whenever a blogger published a new post.
Another real world example can be the MVC architecture pattern which uses the 
pattern.
 
Use Cases for the Observer Pattern
You should use the pattern in the following cases:
  • You have a publisher/subscriber model.
  • Objects need to be notified of a change in another objects.
  • You need that the object that notify its state change would not
    know about its subscribers.

Observer pattern helps us to communicate between parent class and its associated or dependent classes. There are two important concepts in observer pattern ‘Subject’ and ‘Observers’. The subject sends notifications while observers receive notifications if they are registered with the subject. Below figure ‘Subject and observers’ shows how the application (subject) sends notification to all observers (email, event log and SMS). You can map this example to publisher and subscriber model. The publisher is the application and subscribers are email, event log and sms.

Figure: - Subject and Observers


Let’s try to code the same example which we have defined in the previous section. First let’s have a look at the subscribers / notification classes. Figure ‘Subscriber classes’ shows the same in a pictorial format. So we have a common interface for all subscribers i.e. ‘INotification’ which has a ‘notify’ method. This interface ‘INotification’ is implemented by all concrete notification classes. All concrete notification classes define their own notification methodology. For the current scenario we have just displayed a print saying the particular notification is executed.


Figure: - Subscriber classes


As said previously there are two sections in an observer pattern one is the observer/subscriber which we have covered in the previous section and second is the publisher or the subject.

The publisher has a collection of arraylist which will have all subscribers added who are interested in receiving the notifications. Using ‘addNotification’ and ‘removeNotification’ we can add and remove the subscribers from the arraylist. ‘NotifyAll’ method loops through all the subscribers and send the notification.


Figure: - Publisher/Subject classes


Now that we have an idea about the publisher and subscriber classes lets code the client and see observer in action. Below is a code for observer client snippet. So first we create the object of the notifier which has collection of subscriber objects. We add all the subscribers who are needed to be notified in the collection.
Now if the customer code length is above 10 characters then tell notify all the subscribers about the same.


Figure: - Observer client code


Another Example:
The following code is an example of how to implement the pattern:
    #region Subject
    public abstract class Subject
    {
        #region Members
        private List<IObserver> _observers;
        #endregion
        #region Ctor
        /// <summary>
        /// Construct a new subject object
        /// </summary>
        public Subject()
        {
            _observers = new List<IObserver>();
        }
        #endregion
        #region Methods
        /// <summary>
        /// Attaches a new observer to the subject
        /// </summary>
        /// <param name="observer">The observer to attach</param>
        public void Attach(IObserver observer)
        {
            _observers.Add(observer);
        }
        /// <summary>
        /// Detaches an observer from the subject
        /// </summary>
        /// <param name="observer">The observer to detach</param>
        public void Detach(IObserver observer)
        {
            _observers.Remove(observer);
        }
        /// <summary>
        /// Notify all the observers about the change in the
        /// subject's state
        /// </summary>
        public void Notify()
        {
            foreach (IObserver observer in _observers)
            {
                observer.Update();
            }
        }
        #endregion
    }
    #endregion
    #region Concrete Subject
    public class ConcreteSubject<T> : Subject
    {
        #region Properties
        /// <summary>
        /// The state of the subject
        /// </summary>
        public T SubjectState { get; set; }
        #endregion
    }
    #endregion
    #region Observer
    public interface IObserver
    {
        void Update();
    }
    #endregion
    #region Concrete Observer
    public class ConcreteObserver<T> : IObserver
    {
        #region Properties
        /// <summary>
        /// The subject the observer holds
        /// </summary>
        public ConcreteSubject<T> Subject { get; set; }
        private T _observerState;
        #endregion
        #region Ctor
        /// <summary>
        /// Construct a new concrete observer with the given
        /// subject
        /// </summary>
        /// <param name="subject">The given subject</param>
        public ConcreteObserver(ConcreteSubject<T> subject)
        {
            Subject = subject;
        }
        #endregion
        #region IObserver Members
        /// <summary>
        /// Make an update to the observer state whenever the
        /// method is callled
        /// </summary>
        public void Update()
        {
            _observerState = Subject.SubjectState;
            Console.WriteLine("The new state of the observer:{0}",
                _observerState.ToString());
        }
        #endregion
    }
    #endregion
The example is simple to follow. We have an IObserver interface and a
Subject abstract class. The observers are registered in the subject with the
Attach method and also can be detached. The subject implement the Notify
method that notifies every observer when the subject state was changed.
When the state changes the observer make an update which is the main
method of the IObserver interface.
The following code is an example scenario of how to run the pattern in
console application:
   ConcreteSubject<string> subject =
      new ConcreteSubject<string>();
   subject.Attach(new ConcreteObserver<string>(subject));
   subject.Attach(new ConcreteObserver<string>(subject));
   subject.SubjectState = "Hello World";
   subject.Notify();
   Console.Read();
Summary To sum up, the observer pattern is widely used and it is very helpful.
You can see the uses of the pattern in the MVC framework for example or even
here in Israel Microsoft blogs when you subscribe to a blog in order to be notified
of new blogger posts.
 


Reference:

No comments:

Post a Comment