4 Observer
4 Observer
1
Observer – A Non Software Example
2
Motivation Weather Station
• Build a weather monitoring station that have
– Weather Station – hardware device which collects data from
various sensors (humidity, temperature, pressure)
– WeatherData object which interfaces with the Weather Station
hardware
• Need to implement three display elements that use the
WeatherData and must be updated each time
WeatherData has new measurements
– a current conditions display Temp, Humidity, Pressure change
– a weather statistics display Avg. temp, Min. temp, Max. temp
– and a forecast display
• The system must be expandable
– can create new custom display elements and can add or remove
as many display elements as they want to the application.
3
A Weather Monitoring Application
What we have What we need
to implement
Temperature sensor
device Weather forecast
Presure sensor
device Current conditions
Weather data
Weather object
station
WeatherData
These three methods return the most recent
weather measurements for temperature,
+ getTemperature() humidity, and pressure respectively.
+ getHumidity()
+ getPressure() We don’t care HOW these variables are set;
+ measurementChanged() the WeatherData object knows how to get
// other methods updated information from the WeatherStation
5
A First Misguided Attempt at the
Weather Station
public class WeatherData {
// instance variable declarations
public void measurementsChanged() {
Grab the most recent
float temp = getTemperature(); measurements by calling the
float humidity = getHumidity(); WeatherData’s getter methods
float pressure = getPressure(); (already implemented)
6
What’s wrong with the first
implementation?
public class WeatherData {
// instance variable declarations
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity(); Area of change, we need
float pressure = getPressure(); to encapsulate this.
8
Publisher + Subscriber = Observer
When data in the WeatherData object
changes, the observers are notified
Weather forecast
The displays have
Weather subscribed with the
data object WeatherData to receive
updates when the
New data values are WeatherData changes
communicated to the observers
in some form when they change Current conditions
register/
subscribe me
10
Adding Observers
• The TV station is now an official observer
– It gets a notification when the Weather object has
changed
11
Removing Observers
• One of the displays asks to be removed as an
observer
Remove /
Unsubscribe me
12
Removing Observers
• All the other observers can get another notification
except the the display that has been recently
removed from the set of observers
13
Design Principle
Strive for loosely coupled designs
between objects that interact.
14
The Constitution of Software Architects
• Encapsulate what varies
• Program through an interface not to an implementation
• Favor Composition over Inheritance
• Classes should be open for extension but closed for
modification
• Strive for loosely coupled designs between objects that
interact.
• ?????????
• ?????????
• ?????????
• ?????????
15
The Observer Pattern
• Define a one-to-many dependency between objects so
that when one object changes state, all its dependents
are notified and updated automatically.
Motivation for
Observer Pattern
16
Structure Observer Pattern
Knows its numerous observers. Provides an interface for
Defines an update interface
attaching and detaching observer objects.
for concrete observers, that
Sends a notification to its observers when its state changes.
gets called when the
Subject
<<interface>>
Subject’s state changes.
0..* Observer
+attach(o: Observer)
+detach(o: Observer)
+notify() for all o in observers {
+update()
o.update()
}
18
Consequences
• Abstract coupling between subject and observer
– Subject has a list of observers, each conforming to
the simple interface of the abstract Observer class.
The subject doesn't know the concrete class of any
observer => Coupling is abstract and minimal
– Can belong to different layers of abstraction.
• Support for broadcast communication
– Subject doesn’t need to know its receivers.
• Unexpected updates
– Can be blind to some changes in the subject
(observer doesn’t know “what” has changed in the
subject).
19
Designing the Weather Station
<<Interface>>
Subject <<Interface>> <<Interface>>
0..* Observer DisplayElement
+ registerObserver(o:Observer)
+ removeObserver(o:Observer) + update() + display()
+ notifyObservers()
All weather
components
Subject interface
implement
the Observer ForecastDisplay
interface.
WeatherData + update()
+ display()
+ getTemperature() : double
+ getHumidity() : double
+ getPressure() : double
+ measurementChanged() CurrentConditionDisplay StatisticDisplay
+ registerObserver(o : Observer)
+ removeObserver(o : Observer) + update() + update()
+ notifyObservers() + display() + display()
21
Implementing the Subject Interface
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature; Added an ArrayList to hold the
private float humidity; Observers, and we create it in
private float pressure; the constructor
public WeatherData() {
observers = new ArrayList<Observer>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) { Here we implement
observers.remove(o);
the Subject Interface
}
public void notifyObservers() {
for (Observer o : observers) {
o.update(temperature, humidity, pressure);
}
}
24
Implementation Issues: Updates
• The simple observer protocol does not specify what
changed in the subject
• More fine-grained update protocols may specify the
extent of the change:
– update(Object changedState)
or cellUpdate (int x, int y, float value)
• Some observers may observe more than one
subject (many-to-many relation) E.g., a graph can
depend on several different sheets
– The update should specify which subject changed:
update(Subject changedSubject)
29
Update Protocols: Push or Pull
• Pull: The subject should provide an interface that
enables observers to query the subject for the required
state information to update their state.
• Push: The subject should send the state information that
the observers may be interested in.
• Pull assumes no knowledge of the subject about its
observers, so it is more re-usable but less efficient.
• Push assumes that the subjects has some knowledge
about what the observers need, so it is less re-usable
but more efficient.
• Intermediate: when the observer registers using
attach(), it specifies the kind of events it is interested in.
30
Update Protocols: Push or Pull
public void measurementsChanged() {
setChanged(); We first call the setChanged() to
notifyObservers(); indicate that the state has changed.
}
We aren’t sending a data object with the
notifyObservers() call. The Observers are
aware of the subject and they will use that to
“pull” the latest information from the subject.
31
Summary
• OO Principle in play: "Strive for loosely coupled
designs between objects that interact."
• Main points:
– The Observer pattern defines a one to many
relationship between objects
– Subjects (observables), update Observers using a
common interface
– Observers are loosely coupled in that the Observable
knows nothing about them, other than they implement
the Observer interface.
– You can push or pull data from the Observable when
using the pattern (“pull” is considered more correct)
36
Summary
• Don’t depend on a specific order of notification for your
Observers
• Java has several implementations of the Observer
Pattern including the general purpose
java.util.Observable
• Watch out for issues with java.util.Observable
• Don’t be afraid to create our own version of the
Observable if needed
• Swing makes heavy use of the Observer pattern, as do
many GUI frameworks
• You find this pattern in other places as well including
JavaBeans and RMI.
37