Observer pattern

From Wikipedia, the free encyclopedia

The observer pattern (sometimes known as publish/subscribe) is a design pattern 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. In some programming languages, the issues addressed by this pattern are handled in the native event handling syntax. This is a very interesting feature in terms of real-time deployment of applications.


Contents

[edit] Overview

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.

[edit] Participant classes

The participants of the pattern are detailed below. Member functions are listed with bullets.

[edit] Subject

This abstract class provides an interface for attaching and detaching observers. Subject class also holds a private list of observers. Contains these functions (methods):

  • Attach - Adds a new observer to the list of observers observing the subject.
  • Detach - Removes an existing observer from the list of observers observing the subject
  • Notify - Notifies each observer by calling the notify() function in the observer, when a change occurs.

[edit] ConcreteSubject

This class provides the state of interest to observers. It also sends a notification to all observers, by calling the Notify function in its superclass (i.e, in the Subject class). Contains this function:

  • GetState - Returns the state of the subject.

[edit] Observer

This class defines an updating interface for all observers, to receive update notification from the subject. The Observer class is used as an abstract class to implement concrete observers. Contains this function:

  • Notify - An abstract function, to be overridden by concrete observers.

[edit] ConcreteObserver

This class maintains a reference with the ConcreteSubject, to receive the state of the subject when a notification is received. Contains this function:

  • Notify - This is the overridden function in the concrete class. When this function is called by the subject, the ConcreteObserver calls the GetState function of the subject to update the information it has about the subject's state.

When the event is raised each observer receives a callback. This may be either a virtual function of the observer class (called 'notify()' on the diagram) or a function pointer (more generally a function object or "functor") passed as an argument to the listener registration method. The notify function may also be passed some parameters (generally information about the event that is occurring) which can be used by the observer.

Each concrete observer implements the notify function and as a consequence defines its own behavior when the notification occurs.

[edit] Typical usages

  • When an absraction has two aspects, one dependent on the other. Encapsulating these aspects in seperate objects lets vary and reuse them independently.
  • When a change to one object requires changing others, and don't know how many objects need to be changed.
  • When an object should be able to notify other objects without making assumptions about who these objects are.

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.

An example is Java Swing, in which the model is expected to issue change notifications to the views via the PropertyChangeNotification infrastructure. Model classes are Java beans that behave as the subject, described above. View classes are associated with some visible item on the GUI and behave as the observers, described above. As the application runs, changes are made to the model. The user sees these changes because the views are updated accordingly.

[edit] Examples

[edit] C#

using System;
using System.Collections;
 
namespace Wikipedia.Patterns.Strategy
{
        // IObserver --> interface for the observer
        public interface IObserver
        {
                // called by the subject to update the observer of any change
                // The method parameters can be modified to fit certain criteria
                void Update(string message);
        }
 
        public class Subject
        {
                // use array list implementation for collection of observers
                private ArrayList observers;
 
                // constructor
                public Subject()
                {
                        observers = new ArrayList();
                }
 
                public void Register(IObserver observer)
                {
                        // if list does not contain observer, add
                        if (!observers.Contains(observer))
                        {
                                observers.Add(observer);
                        }
                }
 
                public void Unregister(IObserver observer)
                {
                        // if observer is in the list, remove
                        if (observers.Contains(observer))
                        {
                                observers.Remove(observer);
                        }
                }
 
                public void Notify(string message)
                {
                        // call update method for every observer
                        foreach (IObserver observer in observers)
                        {
                                observer.Update(message);
                        }
                }
        }
 
        // Observer1 --> Implements the IObserver
        public class Observer1 : IObserver
        {
                public void Update(string message)
                {
                        Console.WriteLine("Observer1:" + message);
                }
        }
 
        // Observer2 --> Implements the IObserver
        public class Observer2 : IObserver
        {
                public void Update(string message)
                {
                        Console.WriteLine("Observer2:" + message);
                }
        }
 
        // Test class
        public class ObserverTester
        {
                [STAThread]
                public static void Main()
                {
                        Subject mySubject = new Subject();
                        IObserver myObserver1 = new Observer1();
                        IObserver myObserver2 = new Observer2();
 
                        // register observers
                        mySubject.Register(myObserver1);
                        mySubject.Register(myObserver2);
 
                        mySubject.Notify("message 1");
                        mySubject.Notify("message 2");
                }
        }
}

[edit] Python

The observer pattern in Python:

class AbstractObserve_me:
    def __init__(self):
        pass
    def register (self, listener):
        raise NotImplementedError, "Must subclass me"
 
    def unregister (self, listener):
        raise NotImplementedError, "Must subclass me"
 
    def notify_listeners (self, event):
        raise NotImplementedError, "Must subclass me"
 
class Listener:
    def __init__(self, name, subject):
        self.name = name
        subject.register(self)
 
    def notify(self, event):
        print self.name, "received event", event
 
class Subject(AbstractObserve_me):
    def __init__(self):
        self.listeners = []
        self.data=None
     #--------------------------
    "Implement abstract Class AbsObserve_me"
    def register (self, listener):
        self.listeners.append(listener)
 
    def unregister (self, listener):
        self.listeners.remove(listener)
 
    def notify_listeners (self, event):
        for listener in self.listeners:
            listener.notify(event)
    #----------
    def getUserAction(self):
        self.data = raw_input('Enter something to do:')
        return self.data
 
 
 
if __name__=="__main__":
        # make a subject object to spy on
        subject = Subject()
 
        # register two listeners to monitor it.
        listenerA = Listener("<listener A>", subject)
        listenerB = Listener("<listener B>", subject)
 
        # simulated event
        subject.notify_listeners ("<event 1>")
        # outputs:
        #     <listener A> received event <event 1>
        #     <listener B> received event <event 1>
 
        action = subject.getUserAction()
        subject.notify_listeners(action)
        #Enter something to do:hello
        # outputs:
        #     <listener A> received event hello
        #     <listener B> received event hello

The observer pattern can be implemented more succinctly in Python using function decorators.

[edit] Java

Here is an example that takes keyboard input and treats each input line as an event. The example is built upon the library classes java.util.Observer and java.util.Observable. When a string is supplied from System.in, the method notifyObserver is then called, in order to notify all observers of the event's occurrence, in the form of an invocation of their 'update' methods - in our example, ResponseHandler.update(...).

The file myapp.java contains a main() method that might be used in order to run the code.

/* File Name : EventSource.java */
 
package OBS;
import java.util.Observable;          //Observable is here
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class EventSource extends Observable implements Runnable 
{
    public void run()
    {
        try
        {   
            final InputStreamReader isr = new InputStreamReader( System.in );
            final BufferedReader br = new BufferedReader( isr );
            while( true )
            {
                final String response = br.readLine();
                setChanged();
                notifyObservers( response );
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}
/* File Name: ResponseHandler.java */
 
package OBS;
 
import java.util.Observable;
import java.util.Observer;  /* this is Event Handler */
 
public class ResponseHandler implements Observer
{
    private String resp;
    public void update (Observable obj, Object arg)
    {
        if (arg instanceof String)
        {
            resp = (String) arg;
            System.out.println("\nReceived Response: "+ resp );
        }
    }
}
/* Filename : myapp.java */
/* This is main program */
 
package OBS;
 
public class myapp
{
    public static void main(String args[])
    {            
        System.out.println("Enter Text >");
 
        // create an event source - reads from stdin
        final EventSource evSrc = new EventSource();
 
        // create an observer
        final ResponseHandler respHandler = new ResponseHandler();
 
        // subscribe the observer to the event source
        evSrc.addObserver( respHandler );
 
        // starts the event thread
        Thread thread = new Thread(evSrc);
        thread.start();
    }
}

[edit] Implementations

The observer pattern is implemented in numerous programming libraries and systems, including almost all GUI toolkits.

Some of the most notable implementations of this pattern:

[edit] References

http://www.research.ibm.com/designpatterns/example.htm
http://msdn.microsoft.com/en-us/library/ms954621.aspx

[edit] See also

[edit] External links