The Observer Pattern (Behavioral) ©SoftMoore ConsultingSlide 1.
-
Upload
christine-shepherd -
Category
Documents
-
view
222 -
download
0
description
Transcript of The Observer Pattern (Behavioral) ©SoftMoore ConsultingSlide 1.
The Observer Pattern(Behavioral)
©SoftMoore Consulting Slide 1
Motivation
• For many applications there is a need to maintain consistency between related objects without making classes tightly coupled.
• GUI toolkits need to separate the presentation aspects of the user interface from the underlying application data. (Recall the notions of models and views from the discussion of the MVC pattern.)
• For example, the data in a spreadsheet can be displayed in multiple ways, including– a table– a bar chart– a pie chart
©SoftMoore Consulting Slide 2
Motivation(continued)
©SoftMoore Consulting Slide 3
Spreadsheet Data
Table View Bar Graph Pie Chart
request/modification
change notification
Observer Pattern
• Intent: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
• Also Known As: Publish-Subscribe, Model-View• Applicability: Use the Observer pattern
– when a change to one object requires changing others, and you 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; i.e., you don’t want these objects tightly coupled.
– when an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
©SoftMoore Consulting Slide 4
Observer Pattern(continued)
©SoftMoore Consulting Slide 5
Subject
attach(Observer)detach(Observer)notify()
ConcreteSubject
subjectState
getState()setState()
Observer
update()
ConcreteObserver
observerState
update()
for each o in observers o.update()
*observers
Structure
subject
observerState = subject.getState()
©SoftMoore Consulting
Observer Pattern(continued)
Participants• Subject
– knows its observers. Any number of Observer objects may observe a subject.
– provides an interface for attaching and detaching Observer objects.
• Observer– defines an updating interface for objects that should be notified
of changes in a subject.
• ConcreteSubject– stores state of interest to ConcreteObserver objects.– sends a notification to its observers when its state changes.
Slide 6
©SoftMoore Consulting
Observer Pattern(continued)
Participants (continued)
• ConcreteObserver– maintains a reference to a ConcreteSubject object.– stores state that should stay consistent with the subject’s state.– implements the Observer updating interface to keep its state
consistent with the subject’s state.
Slide 7
Observer Pattern(continued)
Collaborations• ConcreteSubject notifies its observers whenever a
change occurs that could make its observers’ state inconsistent with its own.
• After being informed of a change in the concrete subject, a ConcreteObserver object may query the subject for information. ConcreteObserver uses this information to reconcile its state with that of the subject.
©SoftMoore Consulting Slide 8
Observer Pattern(continued)
©SoftMoore Consulting Slide 9
: Observer: Subject : Observer
update()
Collaborations (continued)
setState()
notify()
getState()
update()
getState()
Observer Pattern(continued)
Consequences• Minimal coupling between the Subject and the Observer
– Subjects can be reused without reusing their observers, and vice versa.
– Observers can be added without modifying the subject.– A subject knows only that it has a list of observers.– A subject does not need to know the concrete class of an
observer, just that each observer implements the update interface.
– Subject and observer can belong to different abstraction layers.
• Support for event broadcasting– Subject sends notification to all subscribed observers.– Observers can be added/removed at any time.
©SoftMoore Consulting Slide 10
Observer Pattern(continued)
Consequences (continued)
• Possible cascading of notifications– Observers are not necessarily aware of each other and must be
careful about triggering updates.– Simple update interface provides no details on what changed in
the subject. Observers are required to deduce changes to the subject.
©SoftMoore Consulting Slide 11
Observer Pattern(continued)
Implementation• Mapping subjects to their observers.
– simplest way is for subject to maintain a list of explicit references to its observers (storage overhead).
– can use a hash table to maintain subject-to-observer mapping.
• Observing more than one subject.– must modify the update interface to let the observer know the
identity of the subject that sent the update notification; e.g.,notify(this);
• Who triggers the update?– require subject’s state-setting methods to call notify().– make clients responsible for calling notify() after a change.
©SoftMoore Consulting Slide 12
Observer Pattern(continued)
Implementation (continued)
• How to handle dangling references to deleted subjects.• Making sure Subject state is self consistent before
notification.– can be avoided by sending notifications from Template Methods
in the abstract Subject class.
• Avoiding observer-specific update protocols.– push model: subject sends observers detailed information
about the change, whether they want it or not.– pull model: subject sends nothing but the notification that it
changed, and observers must query the subject to determine what changed and whether or not they need to handle it.
©SoftMoore Consulting Slide 13
Observer Pattern(continued)
Implementation (continued)• Specifying modifications of interest explicitly.
– can improve efficiency by extending a subject’s interface to allow observers to register for specific events of interest
– subjects have aspects, and observers can register interest in some aspects but not others.
• Encapsulating complex update semantics; e.g., by using a ChangeManager object with these responsibilities:– maps subjects to observers– defines update strategy– updates all dependent observers at the request of a subject.
©SoftMoore Consulting Slide 14
Observer Pattern in Java
• Package java.util provides– an interface Observer that observers can implement when they
need to be identified of a change.– a class named Observable that subjects can extend that
manages the list of observers.
• Java Message Service (JMS) supports a publish/subscribe model for messaging that is based on the observer pattern.
• Since version 1.1, the Java event model is based on the observer pattern.
©SoftMoore Consulting Slide 15
The next few slides provide additional details onthese examples of the Observer Pattern in Java.
From Package java.util
public interface Observer { public void update(Observable o, Object arg); }
public class Observable { public synchronized void addObserver(Observer o); public synchronized void deleteObserver(Observer o); public void notifyObservers(); public void notifyObservers(Object arg); ... }
©SoftMoore Consulting Slide 16
©SoftMoore Consulting
JMS
• The Java Message Service (JMS) is a messaging API that allows application components to create, send, receive, and read messages. It enables distributed communication that is loosely coupled, reliable, and asynchronous.
• The JMS API supports two models for messaging:– point-to-point– publish/subscribe
• The publish/subscribe model is essentially an implementation of the observer pattern.
Slide 17
©SoftMoore Consulting Slide 18
Event Sources, Listeners, and Objects
• Events are transmitted from event sources (e.g., buttons or scrollbars) to event listeners.
• An event source is an object that knows when/how the event occurs. Event sources report on events.
• An event listener is an object that needs to be notified when a certain event occurs in order to perform some action in response to the event. Any object can be designed to be an event listener.
• Information about the event is encapsulated in an event object. The class of an event object must ultimately inherit from java.util.EventObject.
©SoftMoore Consulting Slide 19
Summary of Event Handling in Java
• An event source must be able to register listener objects and send them event objects.
• A listener object implements a special listener interface.• When an event occurs, the source notifies all registered
listeners by calling the appropriate method of the listener interface.
• When a listener is notified that an event has occurred, it is up to the listener to determine the appropriate course of action (including ignoring the event).
©SoftMoore Consulting Slide 20
Illustration of Relationship BetweenEvent Sources and Listeners
EventSource
EventSource
EventListener
EventListener
EventListener
EventSource
listens toall threesources
listens toonly onesource
has onlyone listener
has twolisteners
has twolisteners
listens toonly onesource
©SoftMoore Consulting Slide 21
Handling Button Events
• When a button is pushed, it generates an object of class ActionEvent
• A button is an event source for an ActionEvent, so it allows objects to register as listeners for such events; it provides method addActionListener(ActionListener l)
java.util.EventObject
java.awt.AWTEvent
java.awt.ActionEvent
©SoftMoore Consulting Slide 22
Handling Button Events(continued)
• If another object wants to be notified when a button is pushed, the object will need to– implement the ActionListener interface
public interface ActionListener extends EventListener { /** * Invoked when an action occurs. */ public void actionPerformed(ActionEvent e); }
– register with the button by calling its addActionListener() method
©SoftMoore Consulting Slide 23
Example: ButtonCounter
package com.softmoore.swing;
import java.awt.*;import java.awt.event.*;import javax.swing.*;
public class ButtonCounter { public static void main(String[] args) { ButtonCounterFrame frame = new ButtonCounterFrame(); frame.setVisible(true); } }
©SoftMoore Consulting Slide 24
Example: ButtonCounter(continued)
class ClickCountingLabel extends JLabel implements ActionListener { private static final String LABEL_TEXT_PREFIX = "Number of button clicks = ";
private int numClicks = 0;
public ClickCountingLabel() { super(); setText(LABEL_TEXT_PREFIX + numClicks); }
public void actionPerformed(ActionEvent event) { ++numClicks; setText(LABEL_TEXT_PREFIX + numClicks); } }
©SoftMoore Consulting Slide 25
Example: ButtonCounter(continued)
class ButtonCounterFrame extends JFrame { public ButtonCounterFrame() { // ... set up the frame and center it on the screen // ... create panels for the button and label ClickCountingLabel label = new ClickCountingLabel(); labelPanel.add(label);
JButton button = new JButton("Click Me!"); button.addActionListener(label); buttonPanel.add(button);
add(buttonPanel, BorderLayout.NORTH); add(labelPanel, BorderLayout.CENTER);
// ... add panels to frame (to its content pane) } }
©SoftMoore Consulting Slide 26
Example: ButtonCounter(continued)
button is an event sourcelabel is an event listener
addActionListener(label)
©SoftMoore Consulting Slide 27
Sequence Diagram for the Example
: JButton label : CountingLabel
doClick()
actionPerformed(ev)
: ButtonCounterFrame
«create»
ev : ActionEvent
event source event listener event object
«create»
«create»
©SoftMoore Consulting
Related Patterns
• If a ChangeManager is used, it acts as a Mediator between subjects and observers.
• A ChangeManager would often be implemented as a Singleton.
Slide 28
©SoftMoore Consulting
References
• Observer pattern (Wikipedia)http://en.wikipedia.org/wiki/Observer_pattern
• Observer Pattern (Object-Oriented Design)http://www.oodesign.com/observer-pattern.html
• Exploring the Observer Design Pattern(Purdy and Richter)http://msdn.microsoft.com/en-us/library/ee817669.aspx
Slide 29