| Observer Pattern |
Article Index for Observer |
Website Links For Observer |
Information AboutObserver Pattern |
| CATEGORIES ABOUT OBSERVER PATTERN | |
| software design patterns | |
| articles with example python code | |
|
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 that may be raised by the observed object (the '''subject'''). (The object that 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:
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:
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:
ConcreteObserver This class maintains a reference with the ConcreteSubject, to receive the state of the subject when a notification is received. Contains this function:
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:
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. C# IMPLEMENTATION
public interface ISubject { void RegisterObserver(IObserver observer); void UnregisterObserver(IObserver observer); void NotifyObservers(); }
public interface IObserver { void Update(); }
using System.Collections; public class Subject : ISubject { //use array list implementation for collection of observers ArrayList observers; //decoy item to use as counter int counter; //constructor public Subject() { observers = new ArrayList(); counter = 0; } public void RegisterObserver(IObserver observer) { //if list does not contain observer, add if(!observers.Contains(observer) { observers.Add(observer); } } public void UnregisterObserver(IObserver observer) { //if observer is in the list, remove if(observers.Contains(observer)) { observers.Remove(observer); } } public void NotifyObservers() { //call update method for every observer foreach(IObserver observer in observers) { observer.Update(); } } //use function to illustrate observer function //the subject will notify only when the counter value is divisible by 5 public void Operate() { for(counter = 0; counter < 26; counter++) { if(counter % 5 == 0) { NotifyObservers(); } } } }
public class Observer :IObserver { //this will count the times the subject changed //evidenced by the number of times it notifies this observer int counter; public Observer() { counter = 0; } //counter is incremented with every notification public void Update() { counter += 1; } //a getter for counter public int Counter { get { return counter; } } }
using System; public class ObserverTester { {Link without Title} public static void Main() { Subject mySubject = new Subject(); Observer myObserver1 = new Observer(); Observer myObserver2 = new Observer(); //register observers mySubject.RegisterObserver(myObserver1); mySubject.RegisterObserver(myObserver2); mySubject.Operate(); //both observers are expected to yield 5 as a result of 5 notifications Console.WriteLine("Observer 1 : {0} notifications.",myObserver1.Counter); Console.WriteLine("Observer 2 : {0} notifications.",myObserver2.Counter); } } 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 = {Link without Title} 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(" listenerB = Listener(" # the subject now has two listeners registered to it. subject.notify_listeners (" # outputs: # # IMPLEMENTATIONS Here is an example that takes keyboard input and treats the input line as an Event. The native 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.
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(); } } }
package OBS; import java.util.Observable;
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(" Received Response: "+ resp ); } } }
package OBS; public class myapp { public static void main(String args {Link without Title} ) { 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:
SEE ALSO
EXTERNAL LINKS
|
|
|