0% found this document useful (0 votes)
17 views

4 Observer

Uploaded by

Hà Ngọc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

4 Observer

Uploaded by

Hà Ngọc
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Observer Pattern

Keeping your Objects in the Know!

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

Humidity sensor Weather statistics


device
4
The WeatherData class

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

This method is called anytime new


weather measurement data is available

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)

currentConditionsDisplay.update(temp, humidity, pressure);


statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
Now update the displays.
Call each display element to
// other WeatherData methods here update its display, passing it the
} most recent measurements.

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.

currentConditionsDisplay.update(temp, humidity, pressure);


statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// other WeatherData methods here
}
At least we seem to be using a common
By coding to concrete interface to talk to the display elements …
implementations we have no way to They all have an update() method that
add or remove other display elements takes temp, humidity and pressure values.
without making changes to the program.
7
CurrentConditionsDisplay Elements
public class CurrentConditionsDisplay {
private float temperature;
private float humidity;

public void update(float temperature, float humidity,


float pressure) {
this.temperature = temperature; When update() is called, we
this.humidity = humidity; save the temp and humidity
display(); and call display()
}
public void display() {
System.out.println("Current conditions : "
+ temperature + "F degrees and "
+ humidity + "% humidity");
}
}

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

This object isn’t an


observer so it doesn’t Observer
get notified when the objects
subject data changes Weather statistics
9
Adding Observers
• A TV station comes along and tells the Weather data
that it wants to become an observer

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.

• Loosely coupled designs allow us to build flexible


OO systems that can handle changes because they
minimize the interdependency between objects.

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()
}

Concrete observers can


be any class that
ConcreteSubject -subject ConcreteObserver implements the Observer
-subjectState: Object interface. Each observer
-obseverState: Object
registers with a concrete
+getState(): Object +update() subject to receive updates.
+setState(o: Object)
A concrete subject always implements the observerState=
subject.getState()
Subject interface. In addition to the register
(attach) and remove (detach) methods, the
concrete subject implements a notify() method
17
to notify observers whenever state changes.
Collaborations
• ConcreteSubject notifies its observers whenever a
change occurs.
• ConcreteObserver object may query the subject for
information to reconcile its state with that of the subject.

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()

WeatherData now implements


the Subject interface. 20
Implementing the Weather Station
public 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(); These are the state values
} the Observers get from the
Subject when a weather
measurement changes.

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);
}
}

public void measurementsChanged() {


Notify the observers when
notifyObservers();
} measurements change.
} 22
The Display Elements The constructors passed
the weatherData object
public class CurrentConditionsDisplay (the subject) and we use
implements Observer, DisplayElement { it to register the display
private float temperature; as an observer.
private float humidity;
public CurrentConditionsDisplay(Subject weatherData) {
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity,
float pressure) {
this.temperature = temperature;
this.humidity = humidity; When update() is called, we
display(); save the temp and humidity
} and call display()
public void display() {
System.out.println("Current conditions : "
+ temperature + "F degrees and "
+ humidity + "% humidity");
}
}
23
TestDrive
public class WeatherStation {

public static void main(String[] args) {


WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay =
new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay =
new StatisticsDisplay(weatherData);
ForecastDisplay forecastDisplay =
new ForecastDisplay(weatherData);

weatherData.setMeasurements(80, 65, 30.4f);


weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}

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.

public void measurementsChanged() {


setChanged();
notifyObservers(this);
}`
A “push” method -- the modified data is
being pushed to the observers.

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

You might also like