Professional Documents
Culture Documents
h
Keeping your g
g
Objects in the know
Hey Jerry, I’m
notifying everyone that the
Patterns Group meeting moved to
Saturday night. We’re going to be
talking about the Observer Pattern.
That pattern is the best! It’s the
BEST, Jerry!
Congratulations!
Inc.
-O-Rama,
Weather
Street
100 Main 45021
Alley, OK
Tornado
rk
nt of Wo
St ate m e e xt genera
tion
d o u r n
to buil
s o n b e in g selected tation!
Congratu
lation itoring S
W e a ther Mon t pending
Internet-b
a s e d
d o n our paten itions
ti o n w il l be b a s e
e n t w e a ther cond
er sta ks cur r ʼd like
The weath object, which trac etric pressure). We ee
ata om thr
WeatherD , humidity, and bar it ia ll y provides
re tha t in and a
(temperatu ate an application w e a th e r statistics
for you to
cre ditions, therData
m e n ts : c urrent con al time as the Wea
e
display ele st, all updated in r asurements.
f o r e c a e n t me
simple e most rec er-O-
je c t a c q u ir e s th
th e r s ta ti on. Weath an
ob ble wea lopers c
th is is a n expanda I so that other deve ht in. Weʼd
Further, to release
an AP them rig
m a w a n ts d is p la y s and plug
Ra er
own weath at API!
write their supp th ly e ss model:
once
r y o u to a t b u s in
like fo
ks we hav
e a gre for each
a th in to c h a rge them
-R a m te n d to pay
Weather-O s are hooked, we in part: we are going
er est
the custom use. Now for the b
e y
display th options. lp ha applica
tion.
s to c k n a n d a
you in ur desig
r w a r d to seeing yo
o
We look f
,
Sincerely
s to you.
u r r ic a ne, CEO e r D a ta source file
Johnny H the Wea th
e a r e o v ernighting
P.S. W
Chapter 2
the observer pattern
Humidity displays
pulls data Current
sensor device Conditions
Temp: 72°
Humidity: 60
Pressure:
Temperature
sensor device WeatherData
object
Weather Station
Display device
Pressure
sensor device
The WeatherData object knows how to talk to the physical Weather Station, to get
updated data. The WeatherData object then updates its displays for the three different
display elements: Current Conditions (shows temperature, humidity, and pressure),
Weather Statistics, and a simple forecast.
t
n t h e m ost recenmidity
retur e, hu
WeatherData
e t h r e e methods s for temperatur
Thes measurement respectively.
getTemperature() weather metric pressure s a r
e
e set; th d
b a r o ia b le e
getHumidity() and se var pdat
’t c a r e HOW the ows how to get u
getPressure() n
We do Data object k tation. n
Weather the Weather S
measurementsChanged()
info from
// other methods
/*
* This method gets called
* whenever the weather measurements
* have been updated
*
rData
of the Weathe */
The developers a clue about what we public void measurementsChanged() {
object left us // Your code goes here
need to add... }
Current
Conditions Our job is to implement measurementsChanged()
Temp: 72° so that it updates the three displays for current
Humidity: 60 conditions, weather stats, and forecast.
Pressure:
Display device
the observer pattern
getTemperature()
R The WeatherData class has getter methods for three
getHumidity()
measurement values: temperature, humidity and
barometric pressure. getPressure()
Weather
Stats
Avg. temp: 62°
Min. temp: 50°
Max. temp: 78°
Current
Conditions
R We need to implement three display elements that Temp: 72°
Humidity: 60
use the weather data: a current conditions display, a Pressure:
Display Two
statistics display and a forecast display. These displays
must be updated each time WeatherData has new
Forecast
measurements. Display One
TT
T
Display Three
?
can create new custom display elements and users
can add or remove as many display elements as they
want to the application. Currently, we know about
only the initial three display types (current conditions,
statistics and forecast).
Future displays
first try with the weather station
Here’s a first implementation possibility—we’ll take the hint from the Weather-O-
Rama developers and add our code to the measurementsChanged() method:
t manages
Subject objecdata. 2 Dog Obje
ct
some bit of
2
2
Su int
Cat Object
bje 2
ct Obje
ct
an
This object isn’tdoesn’t
observer, so it
the
Duck Obje
ct get notified whechnanges.
Subject’s data
A day in the life of the Obser ver Pattern
ct
” Dog Obje
me 2
e
rib
bsc Su int
A Duck object comes along u bje
/s ct Obje
ct
ter Cat Object
and tells the Subject that is
eg
it wants to become an “r
observer. t
Mo ec
use Obj
t
Duck really wants in on the Duck Obj ec
Observers
action; those ints Subject is
sending out whenever its state
changes look pretty interesting...
t
Mo ec
use Obj
Observers
8 8
The Subject gets a new 8 ct
Dog Obje
data value! Su int 8
bje
ct Obje
ct
8
Now Duck and all the rest of the ct
Duck Obje Cat Object
observers get a notification that
the Subject has changed.
t
Mo ec
use Obj
Observers
the observer pattern
8
ct
Dog Obje
Su int
The Mouse object asks to be bje
ct Obje
ct
“re
removed as an observer. mo
ve
/u ct
ns Duck Obje Cat Object
The Mouse object has been ub
sc
getting ints for ages and is tired rib
em
of it, so it decides it’s time to e”
stop being an observer. Mo ec
t
use Obj
Observers
8
ct
Dog Obje
Su int
Mouse is outta here! bje
ct Obje
ct
t
Mo ec
use Obj
Observers
Observers
the observer pattern
bje
ct Obje
ct
8
ct
Duck Obje Cat Object
t
Dependen
t
Mo ec
use Obj
subject
ConcreteSubject ConcreteObserver
registerObserver() {...} update()
removeObserver() {...} // other Observer specific
ways
A concrete subjectbjalect notifyObservers() {...} methods
Su
implements the tion to
interface. In addiremove
getState()
Why?
Design Principle
Strive for loosely coupled designs
between objects that interact.
CurrentConditionsDisplay
update()
jec t ThirdPartyDisplay
sub display() { // display current
WeatherData update()
measurements }
registerObserver() display() { // display
removeObserver() something else based on
notifyObservers() measurements }
StatisticsDisplay
This display element update()
getTemperature()
shows the current display() { // display the aver-
Developers
getHumidity()
measurements from th
WeatherData object. e
age, min and max measure-
can implement
getPressure()
measurementsChanged() ments }
the Observer
and Display
ForecastDisplay interfaces to
This one keeps track create their own
WeatherData now
update()
of the min/avg/max display element.
implements the
display() { // display the
measurements and
Subject interface.
forecast }
displays them.
observers.add(o);
}
Likewise, when an observer wants to un-register,
public void removeObserver(Observer o) { we just take it off the list.
int i = observers.indexOf(o);
if (i >= 0) {
Here’s the fun part; this is where we
tell all the observers about the state.
observers.remove(i);
}
} Because they are all Observers, we
know they all implement update(), so
public void notifyObservers() { we know how to notify them.
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
Observers whtens
}
} ify the
We not measuremen
we get updateaedther Station.
from the W
public void measurementsChanged() {
notifyObservers();
}
display() method
+ “F degrees and “ + humidity + “% humidity”);
The
just prints out the mostty.
}
The Weather Station is ready to go, all we need is some code to glue
everything together. Here’s our first attempt. We’ll come back later in
the book and make sure all the components are easily pluggable via a
configuration file. For now here’s how it all works:
the
First, creaattea
public class WeatherStation { WeatherD
public static void main(String[] args) { object.
WeatherData weatherData = new WeatherData();
comment out
these two lines Create the three
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
and run it. weatherData.setMeasurements(78, 90, 29.2f); displays and
} pass them the
WeatherData object.
}
Simulate new weather
measurements.
2 Run the code and let the Observer Pattern do its magic
%java WeatherStation
Current conditions: 80.0F degrees and 65.0% humidity
Avg/Max/Min temperature = 80.0/80.0/80.0
Forecast: Improving weather on the way!
Current conditions: 82.0F degrees and 70.0% humidity
Avg/Max/Min temperature = 81.0/82.0/80.0
Forecast: Watch out for cooler, rainy weather
Current conditions: 78.0F degrees and 90.0% humidity
Avg/Max/Min temperature = 80.0/82.0/78.0
Forecast: More of the same
%
java’s built-in observer pattern
WeatherData setChanged()
’t look
getTemperature()
d o e s n getHumidity()
This liar! Hold to getPressure()
to make to the update()
fami , we’ll get There will be a few changesser s, but basically it’s
tight n a sec... method in the concrete Obcomvermon Observer interface,
this i ich we can the same idea... we have a t’s
Here’s our Subject,Obwh able. We called by the Subject.
rv
now also call the gistseer(), remove() with an update() method tha
don’t need the reers() methods
and notifyObserv t that behavior
anymore; we inheriss.
from the supercla
the observer pattern
each Obser
either notifyObservers() or notifyObservers(Object arg) is notified.
The setChanged() method is used to signify that the state has changed and that notifyObservers(),
when it is called, should update its observers. If notifyObservers() is called without first calling
setChanged(), the observers will NOT be notified. Let’s take a look behind the scenes of
Observable to see how this works:
Behind
the Scenes
Why is this necessary? The setChanged() method is meant to give you more flexibility in how
you update observers by allowing you to optimize the notifications. For example, in our weather
station, imagine if our measurements were so sensitive that the temperature readings were
constantly fluctuating by a few tenths of a degree. That might cause the WeatherData object
to send out notifications constantly. Instead, we might want to send out notifications only if the
temperature changes more than half a degree and we could call setChanged() only after that
happened.
You might not use this functionality very often, but it’s there if you need it. In either case, you
need to call setChanged() for notifications to work. If this functionality is something that is useful
to you, you may also want to use the clearChanged() method, which sets the changed state back to
false, and the hasChanged() method, which tells you the current state of the changed flag.
the observer pattern
ble
serva
Ob
ay(
Displ
t
cas
Fore {
lic )
pub rvable display();
s e
ob
observable.add
Observer(this)
;
implements
public class ForecastDisplay
Observer, DisplayElement {
{
display()
public void y code here
// displa
}
e();
sur e; Pr essur
s t
tPre a.ge
cu rren therDat
e = wea
P ressur sure =
last entPres
curr
private floa
t currentPre
private floa ssure = 29.9
t lastPressu 2f;
re;
WeatherData we
atherData =
(WeatherData)o
bservable;
le,
ble observab
ic void update(Observa
publ
{
Object arg)
servable;
import java.util.Ob
til.Ob server;
import java.u
%java WeatherStation
Forecast: Improving weather on the way!
Avg/Max/Min temperature = 80.0/80.0/80.0
Current conditions: 80.0F degrees and 65.0% humidity
Forecast: Watch out for cooler, rainy weather
Avg/Max/Min temperature = 81.0/82.0/80.0
Current conditions: 82.0F degrees and 70.0% humidity
Forecast: More of the same
Avg/Max/Min temperature = 80.0/82.0/78.0
Current conditions: 78.0F degrees and 90.0% humidity
%
Doesn’t
java.util.Observable
violate our OO design principle
of programming to interfaces
not implementations?
Observable is a class
You already know from our principles this is a bad idea, but what harm does it really
cause?
First, because Observable is a class, you have to subclass it. That means you can’t add
on the Observable behavior to an existing class that already extends another superclass.
This limits its reuse potential (and isn’t that why we are using patterns in the first place?).
Second, because there isn’t an Observable interface, you can’t even create your own
implementation that plays well with Java’s built-in Observer API. Nor do you have
the option of swapping out the java.util implementation for another (say, a new, multi-
threaded implementation).
What to do?
Observable may serve your needs if you can extend java.util.Observable. On the other
hand, you may need to roll your own implementation as we did at the beginning of the
chapter. In either case, you know the Observer Pattern well and you’re in a good position
to work with any API that makes use of the pattern.
observer and swing
Let’s take a look at a simple part of the Swing API, the JButton. If you look under
the hood at JButton’s superclass, AbstractButton, you’ll see that it has a lot of add/
remove listener methods. These methods allow you to add and remove observers,
or as they are called in Swing, listeners, to listen for various types of events that
occur on the Swing component. For instance, an ActionListener lets you “listen in”
on any types of actions that might occur on a button, like a button press. You’ll find
various types of listeners all over the Swing API.
rface.
Here’s our fancy inte
%java SwingObserverExample
Devil answer Come on, do it!
Don’t do it, you might regret it!
Angel answer %
the observer pattern
ication that
Simple Swing apfplrame and
public class SwingObserverExample { just creates a on in it.
JFrame frame; throws a butt
public static void main(String[] args) {
SwingObserverExample example = new SwingObserverExample();
example.go();
}
OO Basics
Observers using a common
interface.
ß Observers are loosely coupled
Abstraction in that the Observable knows
n
Encapsulatio
s
OO Principle
nothing about them, other
m
Polymorphis
than that they implement the
Observer Interface.
Inheritence
a p s u la t e w hat varies. ß You can push or pull data from
En c
osition over
the Observable when using
F a v o r c o m p the pattern (pull is considered
inheritance.
more “correct”).
not
r o g r a m t o interfaces, est
Here’s your newember, ß Don’t depend on a specific
P ions.
implementat principle. Remd designs are order of notification for your
o r lo
d
osely couple that loosely couplelexible and Observers.
St r iv e f much more fchange.
een objects ß Java has several
designs betw resilient to implementations of the
interact. Observer Pattern, including
the general purpose java.util.
Observable.
OO Patterns
ß Watch out for issues with
s, the java.util.Observable
f a m il y of algorithm many implementation.
define s a -to-
Strategy - eeacrhvoenre, -andemfainkess taheomnetorsitshomthat
encapsulaOtebs s
ß Don’t be afraid to create
bejealgc
tbeegtywleetesn toh sutseatite., all its
e n d. eSntc y
r a your own Observable
interchandgep otnlye forbojemcctliecnhtas ntgheast
a b le
nd updated
implementation if needed.
nednen a
vary indewphe ents are n o t if ie d ß Swing makes heavy use of the
depend lly
automatica
Observer Pattern, as do many
GUI frameworks.
ß You’ll also find the pattern in
A new pattern for communicating state to a many other places, including
set of objects in a loosely coupled manner. We JavaBeans and RMI.
haven’t seen the last of the Observer Pattern
- just wait until we talk about MVC!