Observer pattern
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.
The essence of this pattern is that one or more objects (called observers or listeners) are registered (or register themselves) to observe an event which may be raised by the observed object (the subject). (The object which may raise an event generally maintains a collection of the observers.)
The UML diagram below illustrates this structure:
Participant classes
The participants of the pattern are detailed below. Member functions are listed with bullets.
Subject
This class provides an interface for attaching and detaching observers. Subject class also holds a private list of observers. Contains these functions:
- Attach - Adds a new observer to the list of observers observing the subject.
- Detach - Removes an 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.
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 super class (i.e, in the Subject class). Contains this function:
- GetState - Returns the state of the subject.
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 overriden by concrete observers.
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.
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.
Typical usages
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 an object property. Note that often callbacks called in response to a property value change the values of some properties, possibly causing an event cascade.
- In a mailing list, where every time 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.
Pseudocode
This pseudocode, written in a Python -esque syntax, demonstrates the observer pattern.
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:
def __init__(self):
self.listeners = []
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)
subject = Subject()
listenerA = Listener("<listener A>", subject)
listenerB = Listener("<listener B>", subject)
# the subject now has two listeners registered to it.
subject.notify_listeners ("<event 1>")
# outputs:
# <listener A> received event <event 1>
# <listener B> received event <event 1>
Implementations
Here is an Example that takes key board input and treat the input line as an Event. The Event is notified by notifyObserver method. This is caught by ResponseHandler. The myapp.java is main application and can be run as main program. Store this file under OBS directory and compile all. run as: java myapp
/* 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 { String response;
public void run() { try {
InputStreamReader isr = new InputStreamReader(System.in );
BufferedReader br = new BufferedReader(isr);
while( true ) { 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 >");
EventSource evSrc = new EventSource();
ResponseHandler respHandler = new ResponseHandler();
evSrc.addObserver (respHandler);
evSrc.run();
} }
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:
- Here is an implementation of observer pattern in Objective-C
- The Java Swing library makes extensive use of the observer pattern for event management
- Boost.Signals, an extension of the C++ STL providing a signal/slot model
- The Qt C++ framework's signal/slot model
- libsigc++ - the C++ signalling template library.
- sigslot - C++ Signal/Slot Library
- XLObject - Template-based C++ signal/slot model patterned after Qt.
- GLib - an implementation of objects and signals/ callbacks in C. (This library has many bindings to other programming languages.)
- Exploring the Observer Design Pattern - the C Sharp (C#) and Visual Basic .NET implementation, using delegates and the Event pattern
- Using the Observer Pattern , a discussion and implementation in REALbasic
- flash.events , a package in ActionScript 3.0 (following from the mx.events package in ActionScript 2.0).
- CSP - Observer Pattern using CSP-like Rendezvous (each actor is a process, communication is via rendezvous).
- YUI Event utility implements custom events through the observer pattern
- Py-notify, a Python implementation
See also
- Design Patterns, the book which gave rise to the study of design patterns in computer science
- Design pattern (computer science) , a standard solution to common problems in software design
没有评论:
发表评论