Observer Pattern Khali Young 2006 Aug


Published on

Published in: Technology, Business
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Observer Pattern Khali Young 2006 Aug

  1. 1. The Observer Pattern
  2. 2. A Problem <ul><li>Multiple displays need to be updated with weather data from a single weather station </li></ul>
  3. 3. A naive solution <ul><li>public class WeatherData { </li></ul><ul><li>// instance variable declarations </li></ul><ul><li>public void measurementsChanged() { </li></ul><ul><li>float temperature = getTemperature(); </li></ul><ul><li>float humidity = getHumidity(); </li></ul><ul><li>float pressure = getPressure(); </li></ul><ul><li>currentConditionsDisplay.update(temperature, humidity, pressure); </li></ul><ul><li>statisticsDisplay.update(temperature, humidity, pressure); </li></ul><ul><li>forecastDisplay.update(temperature, humidity, pressure); </li></ul><ul><li>} </li></ul><ul><li>// other weather data methods here </li></ul><ul><li>} </li></ul>
  4. 4. What’s Wrong with this Solution? <ul><li>How are the following design principles contradicted? </li></ul><ul><ul><li>Identify the aspects of your application that vary and separate them from what stays the same. </li></ul></ul><ul><ul><li>Program to an interface, not an implementation. </li></ul></ul><ul><ul><li>Strive for loosely coupled designs between objects that interact </li></ul></ul>
  5. 5. Enter the Observer Pattern <ul><li>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. </li></ul>
  6. 6. Interaction of a Subject and Observers
  7. 7. Back to our Problem: Interfaces <ul><li>public interface Subject { </li></ul><ul><li>public void registerObserver(Observer o); </li></ul><ul><li>public void removeObserver(Observer o); </li></ul><ul><li>public void notifyObservers(); </li></ul><ul><li>} </li></ul><ul><li>public interface Observer { </li></ul><ul><li>public void update(float temp, float humidity, float pressure); </li></ul><ul><li>} </li></ul><ul><li>public interface DisplayElement { </li></ul><ul><li>public void display(); </li></ul><ul><li>} </li></ul>
  8. 8. Implementing Subject (I) <ul><li>public class WeatherData implements Subject { </li></ul><ul><li>private ArrayList observers; </li></ul><ul><li>private float temperature; </li></ul><ul><li>private float humidity; </li></ul><ul><li>private float pressure; </li></ul><ul><li>public WeatherData() { </li></ul><ul><li>observers = new ArrayList(); </li></ul><ul><li>} </li></ul><ul><li>public void registerObserver(Observer o) { </li></ul><ul><li>observers.add(o); </li></ul><ul><li>} </li></ul><ul><li>public void removeObserver(Observer o) { </li></ul><ul><li>int i = observers.indexOf(o); </li></ul><ul><li>if (i >= 0) { </li></ul><ul><li>observers.remove(i); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  9. 9. Implementing Subject (II) <ul><li>public void notifyObservers() { </li></ul><ul><li>for (int i = 0; i < observers.size(); i++) { </li></ul><ul><li>Observer observer = (Observer)observers.get(i); </li></ul><ul><li>observer.update(temperature, humidity, pressure); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>public void measurementsChanged() { </li></ul><ul><li>notifyObservers(); </li></ul><ul><li>} </li></ul><ul><li>public void setMeasurements(float temperature, float humidity, float pressure) { </li></ul><ul><li>this.temperature = temperature; </li></ul><ul><li>this.humidity = humidity; </li></ul><ul><li>this.pressure = pressure; </li></ul><ul><li>measurementsChanged(); </li></ul><ul><li>} </li></ul><ul><li>// other WeatherData methods here - getters </li></ul><ul><li>} </li></ul>
  10. 10. Implementing Observer <ul><li>public class CurrentConditionsDisplay implements Observer, DisplayElement { </li></ul><ul><li>private float temperature; </li></ul><ul><li>private float humidity; </li></ul><ul><li>private Subject weatherData; </li></ul><ul><li>public CurrentConditionsDisplay(Subject weatherData) { </li></ul><ul><li>this.weatherData = weatherData; </li></ul><ul><li>weatherData.registerObserver(this); </li></ul><ul><li>} </li></ul><ul><li>public void update(float temperature, float humidity, float pressure) { </li></ul><ul><li>this.temperature = temperature; </li></ul><ul><li>this.humidity = humidity; </li></ul><ul><li>display(); </li></ul><ul><li>} </li></ul><ul><li>public void display() { </li></ul><ul><li>System.out.println(&quot;Current conditions: &quot; + temperature </li></ul><ul><li>+ &quot;F degrees and &quot; + humidity + &quot;% humidity&quot;); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  11. 11. Push vs Pull <ul><li>Our current solution “pushes” data to the observers </li></ul><ul><ul><ul><li>public void update(float temperature, float humidity, float pressure) { </li></ul></ul></ul><ul><ul><ul><li>this.temperature = temperature; </li></ul></ul></ul><ul><ul><ul><li>this.humidity = humidity; </li></ul></ul></ul><ul><ul><ul><li>display(); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><li>The observers do not use all of the data. </li></ul><ul><li>What happens if other observers need different data? </li></ul><ul><li>Observers can “pull” the specific data they need from the subject </li></ul><ul><ul><ul><li>public void update(Subject subject) { </li></ul></ul></ul><ul><ul><ul><li>if (subject instanceof WeatherData) { </li></ul></ul></ul><ul><ul><ul><li> WeatherData weatherData = (WeatherData) subject; </li></ul></ul></ul><ul><ul><ul><li>this.temperature = weatherData.getTemperature(); </li></ul></ul></ul><ul><ul><ul><li>this.humidity = weatherData.getHumidity(); </li></ul></ul></ul><ul><ul><ul><li>display(); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul>
  12. 12. The Power of Loose Coupling <ul><li>When two objects are loosely coupled, they can interact, but have very little knowledge of each other. </li></ul><ul><li>The observer Pattern provides an object design where subjects and observers are loosely coupled – Why? </li></ul><ul><ul><li>The only thing the subject knows about an observer is that it implements a certain interface </li></ul></ul><ul><ul><li>We can add new observers at any time. </li></ul></ul><ul><ul><li>We never need to modify the subject to add new types of observers. </li></ul></ul><ul><ul><li>We can reuse subjects or observers independently of each other. </li></ul></ul><ul><ul><li>Changes to either the subject or an observer will not affect the other. </li></ul></ul>
  13. 13. Liabilities of the Observer Pattern <ul><li>Complicates a design when a hard-coded notification will suffice. </li></ul><ul><li>Complicates a design when you have cascading notifications. </li></ul><ul><li>Observers updating the state of a subject can be an issue as more observers are added. </li></ul><ul><li>May cause memory leaks when observers aren’t removed from their subjects. </li></ul><ul><li>Null pointer exceptions can be caused if subjects are deleted without notifying the observers. </li></ul><ul><li>Can be hard to determine what changed on the subject. </li></ul>
  14. 14. Other Implementation Issues <ul><li>Observing more than one subject </li></ul><ul><ul><li>Which subject is calling update()? </li></ul></ul><ul><li>Where is notify() called? </li></ul><ul><ul><li>In state setting methods on the subject; or </li></ul></ul><ul><ul><li>In an external client after several state changes </li></ul></ul><ul><li>Update different observers based on “interest” </li></ul><ul><ul><li>Why update all observers if some observers are only interested in particular state changes. </li></ul></ul><ul><li>Complex update semantics </li></ul><ul><ul><li>Make sure the subject state is self-consistent before notifying the observers. </li></ul></ul><ul><ul><li>Complex dependencies can be encapsulated in an object GoF call a ChangeManager , with the following responsibilities: </li></ul></ul><ul><ul><ul><ul><li>Maps a subject to its observers </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Defines a particular update strategy </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Updates all dependent observers at the request of the subject </li></ul></ul></ul></ul><ul><ul><ul><li>ChangeManager is a mediator and usually a singleton. </li></ul></ul></ul>
  15. 15. Related Patterns <ul><li>Adaptor </li></ul><ul><ul><li>Can be used to allow objects that do not implement the required interface to participate in the Observer Pattern. </li></ul></ul><ul><li>Mediator </li></ul><ul><ul><li>Can be implemented as an observer. Colleague classes act as subjects, sending notifications to the mediator whenever they change state. </li></ul></ul><ul><ul><li>Can mediate complex update semantics in the form of a ChangeManager. </li></ul></ul><ul><li>MVC </li></ul><ul><ul><li>Model as subject and views as observers. </li></ul></ul>
  16. 16. Questions <ul><li>Using the Observer Pattern as part of MVC: </li></ul><ul><ul><li>When could it make sense for controllers to be observers too? </li></ul></ul><ul><ul><li>Would it ever make sense for an Observer (or View) to talk directly to the Subject (or Model)? </li></ul></ul><ul><li>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? </li></ul><ul><li>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). </li></ul><ul><li>Smells indicating the need for the Observer Pattern? </li></ul><ul><li>Pros and cons of push vs pull? </li></ul><ul><li>What implications are there from objects that are both observers and subjects? What about if the observer & subject interfaces are merged? (As in Smalltalk) </li></ul><ul><li>Are delegates in c# a language implementation of the Observer Pattern? Why? </li></ul><ul><li>Real world examples of the Observer Pattern? </li></ul><ul><li>Where can this pattern be found in programming languages and frameworks? Eg the Delegating Event Model in Java </li></ul>