0% found this document useful (0 votes)
71 views41 pages

CS#7250 (Design (Pa1erns (And (Refactoring (: Instructor: Awais Qasim

The document describes the observer pattern and its implementation in a weather monitoring application. The observer pattern allows objects called observers to register with and receive notifications from another object called a subject. When the subject's state changes, it notifies all registered observers. In the weather application, the WeatherData class acts as the subject, storing current weather measurements. Various display classes like CurrentConditionsDisplay act as observers and update their displays when WeatherData's measurements change.

Uploaded by

Hamza Bhatti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views41 pages

CS#7250 (Design (Pa1erns (And (Refactoring (: Instructor: Awais Qasim

The document describes the observer pattern and its implementation in a weather monitoring application. The observer pattern allows objects called observers to register with and receive notifications from another object called a subject. When the subject's state changes, it notifies all registered observers. In the weather application, the WeatherData class acts as the subject, storing current weather measurements. Various display classes like CurrentConditionsDisplay act as observers and update their displays when WeatherData's measurements change.

Uploaded by

Hamza Bhatti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

CS#7250(Design(Pa1erns(and(

Refactoring(

Instructor: Awais Qasim


Observer(Pa1ern(
Observer'Pa*ern'
This pattern keeps objects in the know when something they care
about happens.

Objects can decide at runtime whether they want to be kept


informed or nit.

It is one of the most heavily used patterns in the Java

3
4
5
Weather'Monitoring'Applica7on'
The three players in the system are the

Weather station (the physical device that acquires the actual


weather data)
WeatherData object (that tracks the data coming from the
Weather Station and updates the displays)
Display that shows users the current weather conditions.

Humidity
Sensor

Pulls displays
Data
Temp Weather Weather Data Display
Sensor Station Object Device

Pressure
Sensor 6
7
8
Unpacking'the'WeatherData'class'
These three getter methods return the most recent weather
measurements for temperature, humidity and pressure respectively.

WeatherData

getTemperature()
getHumidity() /*(
getPressure() *(Call(this(method(
measurementsChanged()
*(whenever(measurements(are(
*(Updated(
*/(
Public(void(measurementsChanged(){(
( //(your(code(goes(here(
Update three }(
different displays
Problem'specica7on'
weatherData class has three
getter methods
measurementsChanged()
method called whenever there
is a change
Three display methods needs to
be supported: current
conditions, weather
statistics and simple
forecast
System should be expandable
First'cut'at'implementa7on'

public class WeatherData {

public void measurementsChanged(){


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

currentConditionsDisplay.update (temp, humidity, pressure);


statisticsDisplay.update (temp, humidity, pressure);
forecastDisplay.update (temp, humidity, pressure);
}
// other methods
}
First'cut'at'implementa7on'
public class WeatherData {

public void measurementsChanged(){


float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure(); Area of change which can be
Managed better by encapsulation

currentConditionsDisplay.update (temp, humidity, pressure);


statisticsDisplay.update (temp, humidity, pressure);
forecastDisplay.update (temp, humidity, pressure);
}
// other methods
By coding to concrete implementations
} there is no way to add additional display
elements without making code change
Basis'for'observer'pa*ern'
Fashioned after the publish/subscribe model

Works off similar to any subscription model


Buying newspaper
Magazines
Basis'for'observer'pa*ern'
Observer(Pa1ern(Dened(

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.
Observer'Pa*ern''Class'diagram'

<<interface>> observers <<interface>>


Subject Observer
registerObserver() Update()
removeObserver()
notifyObservers()

ConcreteSubject subject ConcreteObserver

registerObserver() Update()
removeObserver()
notifyObservers()
Observer'pa*ern''power'of'loose'coupling'
The only thing that the subject knows about an observer is
that it implements an interface

Observers can be added at any time and subject need not be


modified to add observers

Subjects and observers can be reused or modified without


impacting the other [as long as they honor the interface
commitments]
Observer'Pa*ern''Weather'data'

<<interface>>
rs
ob serve Observer <<interface>>
<<interface>>
Subject DisplayElement
update()

registerObserver() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay StatisticsDisplay

WeatherData update() update()


registerObserver() display() display()
removeObserver()
notifyObservers() ForecastDisplay
getTemperature()
getPressure()
getHumidity() update()
measurementsChanged() display()
Add a new type of display named
ThirdPartyDisplay in the current
diagram
Observer'Pa*ern''Weather'data'

<<interface>>
rs
ob serve Observer <<interface>>
<<interface>>
Subject DisplayElement
update()

registerObserver() display()
removeObserver()
notifyObservers()

CurrentConditionsDisplay StatisticsDisplay

WeatherData update() update()


registerObserver() display() display()
removeObserver()
notifyObservers() ForecastDisplay
getTemperature()
getPressure()
getHumidity() update()
measurementsChanged() display()
Weather'data'interfaces'

public(interface(Subject({(
( public(void(registerObserver(Observer(o);(
( public(void(removeObserver(Observer(o);(
( public(void(noMfyObservers();(
}(
public(interface(Observer({(
( public(void(update(oat(temp,(oat(humidity,(oat(pressure);(
}(
public(interface(DisplayElement({(
( public(void(display();(
}(
Implemen7ng'subject'interface'

public(class(WeatherData(implements(Subject({(
( private(ArrayList(observers;(
( private(oat(temperature;(
( private(oat(humidity;(
( private(oat(pressure;(
( (
( public(WeatherData()({(
( ( observers(=(new(ArrayList();(
( }(
( (
Register'and'unregister'

( public(void(registerObserver(Observer(o)({(
( ( observers.add(o);(
( }(
( (
( public(void(removeObserver(Observer(o)({(
( ( int(i(=(observers.indexOf(o);(
( ( if((i(>=(0)({(
( ( ( observers.remove(i);(
( ( }(
( }(
No7fy'methods'
public(void(noMfyObservers()({(
( ( for((int(i(=(0;(i(<(observers.size();(i++)({(
( (( Observer(observer(=((Observer)observers.get(i);(
( (( observer.update(temperature,(humidity,(pressure);(
( ( }(
}(
( (
( public(void(measurementsChanged()({(
( ( noMfyObservers();(
}(

public(void(setMeasurements(oat(temperature,(oat(humidity,(oat(pressure)({(
( this.temperature(=(temperature;(
( this.humidity(=(humidity;(
( this.pressure(=(pressure;(
( measurementsChanged();(
}(
Now,'lets'build'those'display'elements'
public 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);
}
}
Why we store a reference to the
Subject? It doesnt look like we use
it again after the constructor?
Complete'Weather'Sta7on'
Output'
Observer(pa1ern(

More(analysis(
Push'or'pull'
The notification approach used so far pushes all the state to
all the observers

One can also just send a notification that some thing has
changed and let the observers pull the state information

Java observer pattern support has built in support for both


push and pull in notification. The most general is the
Observer interface and the Observable class in the
java.util package. These are quite similar to our Subject and
Observer interface, but give you a lot of functionality out of
the box.
Java'Observer'Pa*ern''Weather'data'

<<interface>>
rs
ob serve Observer <<interface>>
Observable
DisplayElement
update()
addObserver()
deleteObserver() display()
notifyObservers()
setChanged()

CurrentConditionsDisplay StatisticsDisplay

WeatherData update() update()


getTemperature() display() display()
getPressure()
getHumidity() ForecastDisplay

update()
display()
How'Javas'builtOin'Observer'Pa*ern'works'
For an Object to become an observer.
Implement the Observer interface and call addObserver() on any
Observable object. Likewise, to remove yourself as an observer just call
deleteObserver().

For the Observable to send notifications


First of all you need to be Observable by extending the
java.util.Observable superclass. From there it is a two
step process:

1) You first must call the setChanged() method to signify


that the state has changed in your object

2) Then, call one of two notifyObservers() methods:

either notifyObservers() or notifyObservers(Object


arg)
Reworking'the'Weather'Sta7on'with'the'builtOin'support'
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public WeatherData() { }
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity,
float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
Reworking'the'Weather'Sta7on'with'the'builtOin'support'
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
Rework'the'CurrentCondi7onsDisplay'
public class CurrentConditionsDisplay implements Observer, DisplayElement{
Observable observable;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
public void display() {
System.out.println(Current conditions: + temperature
+ F degrees and + humidity + % humidity);
}
}
Output'
Problems'with'Java'implementa7on'
Observable is a class
You have to subclass it
You cannot add observable behavior to an existing class
that already extends another superclass
You have to program to an implementation not interface

Observable protects crucial methods


Methods such as setChanged() are protected and not
accessible unless one subclasses Observable.
You cannot favor composition over inheritance.

We may have to roll your own observer interface if Java


utilities dont work for your application
Other'uses'of'the'Observer'pa*ern'in'Java'
GUI interface classes Jbutton

Look at Java API for AbstractButton and Jbutton

It has a lot of add/remove listener methods.

These methods allow us to add and remove observers for


various types of events like a button press.
Summary'so'far..'

Observer pattern Java has several


defines one-to-many implementations of
relationship between observer pattern in
objects util, swing, javabeans
and RMI
We can use push or
pull with observer Swing makes heavy
pattern use of this pattern
Summary(so(far..(
OO(Basics( OO(Pa1erns(
EncapsulaMon( The'Observer'Pa*ern(denes(a(
Inheritance( one#to#many(dependency(
between(objects(so(that(when(
Polymorphism( one(object(changes(state,(all(of(
OO(Principles( its(dependents(are(noMed(and(
Encapsulate(what(varies( updated(automaMcally.(
Favor(composiMon(over( The(Strategy'Pa*ern(denes(a(
inheritance( family(of(algorithms,(
Encapsulates(each(one,(and(
Program(to(interfaces(not(to( makes(them(interchangeable.(
implementaMons( Strategy(lets(the(algorithm(vary(
Strive(for(loosely(coupled(designs( independently(from(clients(that(
between(objects(that(interact( use(it.(

You might also like