Labels

Thursday, November 18, 2010

Observer Design Pattern - Behavioural

1.1          Definition

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.          
To achieve this one object (subject) should know about its dependents. Subject maintains list of its dependents. Each dependent who wants to get notification on subject state change, should register with subject.

1.2          Intent

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
The observer pattern (sometimes known as Publish/Subscribe) is used in computer programming to observe the state of an object in a program. It is related to the principle of Implicit Invocation.
This pattern is mainly used to implement a distributed event handling system. This is a very interesting feature in terms of real-time deployment of applications.

1.3          Motivation

Observer design pattern has two parts and they are subject and observer. The relationship between subject and observer is one-to-many. In order to reuse subject and observer independently, their relationship can't be tightly coupled.

A practical example is graphical interface toolkits that separate the presentational aspect with application data. The presentation aspect is the observer part and the application data is the observer part.

A spreadsheet program can use the observer pattern as the following:



It also allows multiple number of independent observer objects to register a subject at run time.

1.4          Applicability

Use the observer pattern in any of the following situations:

  • When the abstraction has two aspects with one dependent on the other. Encapsulating these aspects in separate objects will increase the chance to reuse them independently.
  • When the subject object doesn't know exactly how many observer objects it has.
  • When the subject object should be able to notify it's observer objects without knowing who these objects are.

1.5          Structure





1.6          Participants

 The classes and/or objects participating in this pattern are:

·         Subject  (Stock)
o   knows its observers. Any number of Observer objects may observe a subject
o   provides an interface for attaching and detaching Observer objects.
·         ConcreteSubject  (IBM)
o   stores state of interest to ConcreteObserver
o   sends a notification to its observers when its state changes
·         Observer  (IInvestor)
o   defines an updating interface for objects that should be notified of changes in a subject.
·         ConcreteObserver  (Investor)
o   maintains a reference to a ConcreteSubject object
o   stores state that should stay consistent with the subject's
o   implements the Observer updating interface to keep its state consistent with the subject's

1.7          Typical Usage

The typical usages of the observer pattern:

·         Listening for an external event (such as a user action). See Event-driven programming.
·         Listening for changes of the value of a property of an object. Note that often callbacks called in response of a property value change also change values of some properties, so sometimes causing an event cascade.
·         In a mailing list, where everytime an event happens (a new product, a gathering, etc.) a message is sent to the people subscribed to the list.

The observer pattern is also very often associated with the Model-view-controller (MVC) paradigm. In MVC, the observer pattern is used to create a loose coupling between the model and the view. Typically, a modification in the model triggers the notification of model observers which are actually the views.

1.8          Consequences

Further benefit and drawback of Observe pattern include:

·         Abstract coupling between subject and observer
·         Support for broadcast communication. The notification is broadcast automatically to all interested objects that subscribed to it
·         Unexpected updates. Observes have no knowledge of each other and blind to the cost of changing in subject. With the dynamic relationship between subject and observers, the update dependency can be hard to track down



1.9          Sample Code

This code demonstrates the Observer pattern in which registered objects are notified of and updated with a state change.


abstract class Subject
{
  private ArrayList observers = new ArrayList();

  public void Attach(Observer observer)
  {
   observers.Add(observer);
  }

  public void Detach(Observer observer)
  {
       observers.Remove(observer);
  }

  public void Notify()
  {
       foreach (Observer o in observers)
       {
         o.Update();
       }
  }
}
abstract class Observer
{
    public abstract void Update();
}
class ConcreteSubject : Subject
    {
        private string subjectState;

        // Property
        public string SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }
    }
class ConcreteObserver : Observer
{
  private string name;
  private string observerState;
  private ConcreteSubject subject;

  public ConcreteObserver(ConcreteSubject subject, string name)
  {
       this.subject = subject;
       this.name = name;
  }

  public override void Update()
  {
       observerState = subject.SubjectState;
       Console.WriteLine("Observer {0}'s new state is {1}",
         name, observerState);
  }

  // Property
  public ConcreteSubject Subject
  {
       get { return subject; }
       set { subject = value; }
  }
}

class MainApp
  {
    static void Main()
    {
       // Configure Observer pattern
       ConcreteSubject s = new ConcreteSubject();

       s.Attach(new ConcreteObserver(s, "X"));
       s.Attach(new ConcreteObserver(s, "Y"));
       s.Attach(new ConcreteObserver(s, "Z"));

       // Change subject and notify observers
       s.SubjectState = "ABC";
       s.Notify();

       // Wait for user
       Console.Read();
   }
 }

Output –

Observer X's new state is ABC
Observer Y's new state is ABC
Observer Z's new state is ABC



1.10       Observer Design Pattern in .NET

The study of design patterns is particularly interesting, as .NET was built with them as a foundation. The Observer pattern seems to appear in many cases throughout the framework.

One of the most visible occurrences of an Observer pattern in .NET is in the implementation of the TraceListener class. Appending individual TraceListener classes to the collection allow them to receive notifications of messages, which can then be consumed. Overriding the default trace listener allows one to write completely customizable code that reacts to a message broadcast from the collection.

Dim myWriter As New TextWriterTraceListener(System.Console.Out)
Trace.Listeners.Add(myWriter)

The trace listener again illustrates the main capabilities of the Observer pattern. The ListenersCollection maintains the master record of the data and broadcasts it to any Observers who have subscribed.

Another example in .NET Framework can be Cache dependency.

In the Cache dependency concept, Cache item validity will depend on the external file or on another cache item.  If a dependency changes, the cache item is invalidated and removed from the cache.  For example, Suppose XML file contains data from which an application reads data and processes and draws different views of graphs.  In such scenarios, applications cache data and will create dependencies on the file from which the data will be read.  Whenever this XML file is updated, Cache data will be removed and the application will reread data and insert again the updated copy of the latest data into the cache.

1.11       Observer Pattern in MSDN

Good object-oriented design emphasizes both encapsulation and loose coupling. In other words, classes should keep internal details private and also minimize their strict dependencies. In most applications, classes don't work in isolation; they interact with many other classes. A common scenario of class interaction occurs when one class (the Observer) needs to be notified when something changes in another (the Subject).

For example, several Windows® Forms controls might need to update their display after a button is clicked. A simple solution would be to have the Subject call a specific method of the Observer whenever a change in state occurs. This introduces a host of problems, however. Now, since the Subject needs to know which method to call, it is tightly coupled to that specific Observer. Furthermore, if you need to add more than one Observer, you have to continue to add code for each method call to the Subject. If the number of Observers changes dynamically, this gets even more complex.

Here, Applying the Observer pattern helps to resolve this problem efficiently. You can decouple the Subject from the Observers so that Observers of any variety can easily be added and removed, at both design time and run time. The Subject maintains a list of interested Observers. Each time the Subject's state changes, it calls the Notify method on each Observer.

While the Gang of Four's Observer pattern solves some of these problems, there are still some roadblocks as below.

·         Subjects must inherit from a specific base class and
·         Also the Observers must implement a special interface – As the Subject (here Subject class in our example) accepts a particular type of Observers (here Observer Interface in our example) in the Attach & Detach methods.

The .NET Framework introduces delegates and events to solve these problems. Events act as the Subject, while delegates act as Observers. Figure 2 shows an example of the Observer pattern, making use of events.

Since EventHandler is a delegate type and not an interface, each Observer doesn't need to implement an extra interface. Assuming it already contains a method with a compatible signature, it only needs to register that method with the event of the Subject. Through delegates and events, the Observer pattern lets you decouple Subjects and their Observers.





Figure 2 Observer Pattern Using Events and Delegates 

public delegate void Event1Hander();
public delegate void Event2Handler(int a);

public class Subject
{
    public Subject(){}

    public Event1Hander Event1;
    public Event2Handler Event2;

    public void RaiseEvent1()
    {
        Event1Handler ev = Event1;
        if (ev != null) ev();
    }

    public void RaiseEvent2()
    {
        Event2Handler ev = Event2;
        if (ev != null) ev(6);
    }
}

public class Observer1
{
    public Observer1(Subject s)
    {
        s.Event1 += new Event1Hander(HandleEvent1);
        s.Event2 += new Event2Handler(HandleEvent2);
    }

    public void HandleEvent1()
    {
        Console.WriteLine("Observer 1 - Event 1");
    }

    public void HandleEvent2(int a)
    {
        Console.WriteLine("Observer 1 - Event 2");
    }
}





Hope this helps.

Thanks & Regards,
Arun Manglick

No comments:

Post a Comment