170 likes | 372 Views
The Observer Pattern. Observer Pattern Context. A system contains objects exhibiting: One-to-many dependency between objects One object changes state All dependents are notified and updated automatically. What are we trying to achieve with the Observer Pattern ?.
E N D
The Observer Pattern SE-2811 Dr. Mark L. Hornick
Observer Pattern Context A system contains objects exhibiting: • One-to-many dependency between objects • One object changes state • All dependents are notified and updated automatically
What are we trying to achieve with the Observer Pattern ? • Separation of software subsystems • Separation between GUI & Domain objects • Loosely-coupled classes • Because tightly-coupled classes reduce reusability & understanding • A generic/elegant way for the classes to communicate
Key components in the Observer Pattern • Subject • Subject has dependent observers. • Observer(s) • When the state of the subject changes, each dependent observer is notified.
Generic Subject class class SubjectClassimplementsSubject { public SubjectClass(); public void attach(Observer obs); public void detach(Observer obs); public void notifyObservers(); private ArrayList<Observer> observers; } Note: Some texts define a notify() instead of notifyObservers() method. However, Java’s Object class already has a notify() method, which we don’t want to override.
Generic Observer class ObserverClassimplementsObserver { public ObserverClass(); public void update(???); } What is the appropriate argument for the update() method?
Basic class relationships Subject ------------------------------ attach():voiddetach():voidnotifyObservers():void Observer---------------- update(???):void -observers 1..* SubjectClass ObserverClass1 ObserverClass2
Collaborations between objects in the Observer pattern s:SubjectClass o1:ObserverClass1 o2:ObserverClass2 attach() attach() notifyObservers() update(???) getContextSpecificInfo() update(???) getContextSpecificInfo()
Weather Program example class WeatherData implements Subject { //private data attributes List<Observer> observers; ... public WeatherData(){…} public void getTemp() {…} public intgetWindSpeed() {…} public void attach(Observer obs) {…} public void detach(Observer obs) {…} public void notifyObservers() {…} ... }
Example (contd.) public void acquireDataFromSensors() { // acquire updated weather data …… notifyObservers(); // notify observers }
Example (contd.) class mainDisplay extends Observer { public mainDisplay (WeatherData wd){...} public void update(???) {...} public void updateDisplayUI() {...} }
Example (contd.) public mainDisplay(WeatherData wd) { SubjectwdSubject = wd; wdSubject.attach(this); } // What do we pass to update()? public void update(???) { // How do we get data from the Subject? updateDisplayUI(???); // mainDisplay class method }
Implementation Questions What should be the arguments of the update method? Should we send the Subject as the argument? Should each instance of the Observer store the “concrete subject” as a data attribute, or just an Interface reference? Can Subject be an abstract class instead of an Interface?
Consequences (positive) Coupling between Subject and Observers: • Subject knows it has a list of Observers, but not specific classes • Each Observer conforms to the simple interface of the abstract Observer Interface. • Hence, coupling is • Minimal • Abstract
Consequences (positive) Cohesion is increased from single-class implementation • State management and display/response are separated • E.g. GUI innards separated from “your code” • E.g. Web access separated from display
Consequences (negative) • Broadcast communication • Notification is broadcast to all interested objects. • Observers can be added/removed at any time. • Observer decides when it needs to be notified. • Unexpected updates • Observers have no knowledge • Of each other’s presence. • About the cost of “state change of subject” • Cascade of updates.