Observer pattern

From Wikipedia, the free encyclopedia

Jump to: navigation, search

The observer pattern (a subset of the asynchronous publish/subscribe 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.

Contents

[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 Update function in the observer, when a change occurs.

The Attach function has an observer as argument. This may be either a virtual function of the observer class (Update in this description) or a function pointer (more generally a function object or functor) in a non object oriented setting.

[edit] ConcreteSubject

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

  • GetState - Return 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:

  • Update - 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:

  • Update - 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.

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

When a change occurs to the (concrete) subject, it sends a notification to all observers, by calling the Notify function. The Notify function then calls the Update function of all attached (concrete) observers. The Notify and Update functions may have parameters indicating what kind of change has occurred to the subject. This allows for optimizations in the observer (only updating those parts that changed).

[edit] Typical usages

  • When an abstraction has two aspects, one is dependent on the other. Encapsulating these aspects in separate objects allows the programmer to vary and reuse them independently.
  • When a change to one object requires changing others, and it's not known in advance 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 UI data binding as in 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

Below 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 notifyObservers 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 )
            {
                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();
    }
}

Here is a very basic implementation of the observer pattern in Python:

from collections import defaultdict
 
class Observable (defaultdict):
 
    def __init__ (self):
        defaultdict.__init__(self, object)
 
    def emit (self, *args):
        '''Pass parameters to all observers and update states.'''
        for subscriber in self:
            response = subscriber(*args)
            self[subscriber] = response
 
    def subscribe (self, subscriber):
        '''Add a new subscriber to self.'''
        self[subscriber]
 
    def stat (self):
        '''Return a tuple containing the state of each observer.'''
        return tuple( self.values() )

In the example above, a Python dictionary is overloaded to accept functions as keys whose return values are stored in corresponding slots in the dictionary. Below is a simple illustration. This class could easily be extended with an asynchronous notification method. Although this example stores functions as keys, it is concievable that one could store user-defined class instances whose methods are accessed in a similar fashion.

myObservable = Observable ()
 
# subscribe some inlined functions.
# myObservable[ lambda x,y: x*y ] would also work here.
myObservable.subscribe( lambda x,y: x*y )
myObservable.subscribe( lambda x,y: float(x)/y )
myObservable.subscribe( lambda x,y: x+y )
myObservable.subscribe( lambda x,y: x-y )
 
# emit parameters to each observer
myObservable.emit (6, 2)
 
# get updated values
myObservable.stat ()         # returns: (8, 3.0, 4, 12)

[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

[edit] See also

[edit] External links

Personal tools