observer pattern khali young 2006 aug

16
The Observer Pattern

Upload: melbournepatterns

Post on 18-Nov-2014

1.683 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Observer Pattern Khali Young 2006 Aug

The Observer Pattern

Page 2: Observer Pattern Khali Young 2006 Aug

A Problem Multiple displays need to be updated with

weather data from a single weather station

Page 3: Observer Pattern Khali Young 2006 Aug

A naive solution

public class WeatherData {

// instance variable declarations

public void measurementsChanged() {

float temperature = getTemperature();float humidity = getHumidity();float pressure = getPressure();

currentConditionsDisplay.update(temperature, humidity, pressure);statisticsDisplay.update(temperature, humidity, pressure);forecastDisplay.update(temperature, humidity, pressure);

}

// other weather data methods here

}

Page 4: Observer Pattern Khali Young 2006 Aug

What’s Wrong with this Solution? How are the following design principles

contradicted? Identify the aspects of your application that

vary and separate them from what stays the same.

Program to an interface, not an implementation.

Strive for loosely coupled designs between objects that interact

Page 5: Observer Pattern Khali Young 2006 Aug

Enter the Observer Pattern

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

Page 6: Observer Pattern Khali Young 2006 Aug

Interaction of a Subject and Observers

Page 7: Observer Pattern Khali Young 2006 Aug

Back to our Problem: Interfacespublic interface Subject {

public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObservers();

}

public interface Observer {public void update(float temp, float humidity, float pressure);

}

public interface DisplayElement {public void display();

}

Page 8: Observer Pattern Khali Young 2006 Aug

Implementing Subject (I)public class WeatherData implements Subject {

private ArrayList observers;private float temperature;private float humidity;private float pressure;

public WeatherData() {observers = new ArrayList();

}

public void registerObserver(Observer o) {observers.add(o);

}

public void removeObserver(Observer o) {int i = observers.indexOf(o);if (i >= 0) {

observers.remove(i);}

}

Page 9: Observer Pattern Khali Young 2006 Aug

Implementing Subject (II)public void notifyObservers() {

for (int i = 0; i < observers.size(); i++) {Observer observer = (Observer)observers.get(i);observer.update(temperature, humidity, pressure);

}}

public void measurementsChanged() {notifyObservers();

}

public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();

}

// other WeatherData methods here - getters}

Page 10: Observer Pattern Khali Young 2006 Aug

Implementing Observerpublic class CurrentConditionsDisplay implements Observer, DisplayElement {

private float temperature;private float humidity;private Subject weatherData;

public CurrentConditionsDisplay(Subject weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);

}

public void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;display();

}

public void display() {System.out.println("Current conditions: " + temperature

+ "F degrees and " + humidity + "% humidity");}

}

Page 11: Observer Pattern Khali Young 2006 Aug

Push vs Pull Our current solution “pushes” data to the observers

public void update(float temperature, float humidity, float pressure) { this.temperature = temperature;

this.humidity = humidity;display();

}

The observers do not use all of the data. What happens if other observers need different data? Observers can “pull” the specific data they need from the

subject

public void update(Subject subject) { if (subject instanceof WeatherData) {

WeatherData weatherData = (WeatherData) subject; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); }}

Page 12: Observer Pattern Khali Young 2006 Aug

The Power of Loose Coupling When two objects are loosely coupled, they can interact,

but have very little knowledge of each other. The observer Pattern provides an object design where

subjects and observers are loosely coupled – Why? The only thing the subject knows about an observer is that it

implements a certain interface We can add new observers at any time. We never need to modify the subject to add new types of

observers. We can reuse subjects or observers independently of each

other. Changes to either the subject or an observer will not affect the

other.

Page 13: Observer Pattern Khali Young 2006 Aug

Liabilities of the Observer Pattern Complicates a design when a hard-coded

notification will suffice. Complicates a design when you have cascading

notifications. Observers updating the state of a subject can be

an issue as more observers are added. May cause memory leaks when observers aren’t

removed from their subjects. Null pointer exceptions can be caused if subjects

are deleted without notifying the observers. Can be hard to determine what changed on the

subject.

Page 14: Observer Pattern Khali Young 2006 Aug

Other Implementation Issues Observing more than one subject

Which subject is calling update()? Where is notify() called?

In state setting methods on the subject; or In an external client after several state changes

Update different observers based on “interest” Why update all observers if some observers are only

interested in particular state changes. Complex update semantics

Make sure the subject state is self-consistent before notifying the observers.

Complex dependencies can be encapsulated in an object GoF call a ChangeManager, with the following responsibilities:

(i) Maps a subject to its observers(ii) Defines a particular update strategy(iii)Updates all dependent observers at the request of the subject

ChangeManager is a mediator and usually a singleton.

Page 15: Observer Pattern Khali Young 2006 Aug

Related Patterns Adaptor

Can be used to allow objects that do not implement the required interface to participate in the Observer Pattern.

Mediator Can be implemented as an observer. Colleague classes

act as subjects, sending notifications to the mediator whenever they change state.

Can mediate complex update semantics in the form of a ChangeManager.

MVC Model as subject and views as observers.

Page 16: Observer Pattern Khali Young 2006 Aug

Questions Using the Observer Pattern as part of MVC:

When could it make sense for controllers to be observers too? Would it ever make sense for an Observer (or View) to talk directly to the Subject

(or Model)? What are the properties of a system that uses the Observer Pattern

extensively? How would you approach the task of debugging code in such a system?

How could you handle concurrency problems with this pattern? Consider an Unregister() message being sent to a subject, just before the subject sends a Notify() message to the ChangeManager (or Controller).

Smells indicating the need for the Observer Pattern? Pros and cons of push vs pull? What implications are there from objects that are both observers and

subjects? What about if the observer & subject interfaces are merged? (As in Smalltalk)

Are delegates in c# a language implementation of the Observer Pattern? Why?

Real world examples of the Observer Pattern? Where can this pattern be found in programming languages and

frameworks? Eg the Delegating Event Model in Java