Search This Blog

Saturday, June 29, 2013

Observer Design Pattern

         Definition in Wikipedia:
"The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems. The Observer pattern is also a key part in the familiar Model View Controller (MVC) architectural pattern. In fact the observer pattern was first implemented in Smalltalk's MVC based user interface framework. The observer pattern is implemented in numerous programming libraries and systems, including almost all GUI toolkits."
          In www.dofactory.com the Observer Design Pattern is the  this:
          

In terms of the .NET Framework the terminology is a bit difference:
The abstract class Observer is replaced by the IObserver  interface.
The  abstract class Subject is replaced by the IObservable  interface.
The class ConcreteSubject usually is called Observable.
The function Attach is replaced by the function Register.
The function Dettach is replaced by the function Unregister
Also under the term  container we mean some generic type collection in which we can have the observers.



The sequence diagram which describes the process of the  Registration is the following.
Ee817669.observerpattern_02(en-us,PandP.10).gif

The sequence diagram which describes the process of the  Unregistration is the following.


Ee817669.observerpattern_04(en-us,PandP.10).gif


The sequence diagram which describes the process of the  Notification is the following:













In this process the key thing is that when a state change occurs (OnxxxChanged), the subject retrieves all the observers within the container by invoking the GetObservers method. The subject then enumerates through the retrieved observers, calling the Notify method, which notifies the observer of the state change.

Principially in .NET Framework we have the following structure:


//interface the all observer classes should implement
public interface IObserver {
   
   void Update(object anObject);
   
}//IObserver

//interface that all observable classes should implement
public interface IObservable {

   void Register(IObserver anObserver);
   void UnRegister(IObserver anObserver);
   void Notify(object anObject)
}//IObservable


//helper class that implements observable interface
public class ObservableImpl:IObservable {
      
   //container to store the observer instance (is not synchronized for 
         this example)
   protected Hashtable _observerContainer=new Hashtable();
   
   //add the observer
   public void Register(IObserver anObserver){
      _observerContainer.Add(anObserver,anObserver); 
   }//Register
      
   //remove the observer
   public void UnRegister(IObserver anObserver){
      _observerContainer.Remove(anObserver); 
   }//UnRegister

   //common method to notify all the observers
   public void Notify(object anObject) { 
         
      //enumeration the observers and invoke their notify method
      foreach(IObserver anObserver in _observerContainer.Keys) { 

         anObserver.Update(anObject); 

      }//foreach
      
   }//NotifyObservers

}//ObservableImpl


//represents a Concrete Subject an application
public class ConcreteSubject:ObservableImpl {
      
   //instance variable 
   object _concreteSubjectField ;

   //property for ConcreteSubjectField 

   public object ConcreteSubjectField {
 
      set {    _ConcreteSubjectField =value;
         base.Notify(_concreteSubjectField );
          }//set
      
   }//ConcreteSubjectField property
 
}//ConcreteSubject  

//represents the user interface in the application
public class ConcreteObserver1:IObserver {

   public void Update(object anObject){ 
      Console.WriteLine("The new ConcreteSubjectField property is:" + anObject); 
   }//Notify

}//ConcreteObserver1

//represents the user interface in the application
public class ConcreteObserver2:IObserver {

   public void Update(object anObject){ 
      Console.WriteLine("The new ConcreteSubjectField property is:" + anObject); 
   }//Notify

}//ConcreteObserver2
public class MainClass{ public static void Main() { //create new display and stock instances ConcreteObserver1 concreteObserver1=new ConcreteObserver1();
      ConcreteObserver2 concreteObserver2=new ConcreteObserver2();
ConcreteSubject concreteSubject =new ConcreteSubject (); //register ConcreteSubject.Register(concreteObserver1);
      ConcreteSubject.Register(concreteObserver2);
//loop 100 times and modify the ConcreteSubjectField for(int looper=0;looper<100 .unregister="" concreteobserver1="" concretesubject.concretesubjectfield="looper;" concretesubject="" looper="" pre="" unregister="">
      ConcreteSubject .UnRegister(concreteObserver2);
}//Main }//MainClass
Notes
1)if you wish to have only one instanse of Concrete Subject then you can apply the Singleton design pattern in this class.
    



I would like to underline  that there are many variations of this pattern.
One very simple example is the following:
public class Issuer
{
    public Issuer()    {
        var observable = new Observable();
        observable.IssueData("Hello World!");    }
}
public class Observable
{
    public event Receive OnReceive;
    

    public void IssueData(string data)    {
        //Add all the observer below
        //1st observer
        IObserver iObserver = new Observer1();
        this.OnReceive += iObserver.ReceiveData;
        //2nd observer
        IObserver iObserver2 = new Observer2();
        this.OnReceive += iObserver2.ReceiveData;

        //publish data 
        var handler = OnReceive;
        if (handler != null)
        {
            handler(data);
        }
    }
}

public interface IObserver
{
    void ReceiveData(string data);
}

//Observer example
public class Observer1 : IObserver
{
    public void ReceiveData(string data)
    {
        //sample observers does nothing with data :)
    }
}

public class Observer2 : IObserver
{
    public void ReceiveData(string data)
    {
        //sample observers does nothing with data :)
    }
}

source

No comments:

Post a Comment

Blog Archive

About Me

An seasoned developer, architect and with some Team Leading exposure, offering full project life cycle experiences within multi cultural, multi National environments and within differing business streams and all primarily on a .Net platform.