Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
17 views39 pages

02 - Observer Pattern

The document discusses the implementation of the Observer Pattern in a weather monitoring application, detailing the roles of the WeatherData class, observers, and display elements. It emphasizes the importance of loose coupling between subjects and observers, allowing for flexibility and scalability in the system. The document also outlines the design and coding of various display elements that respond to changes in weather data, while highlighting potential issues and solutions in the implementation process.

Uploaded by

Batuhan Ekinci
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)
17 views39 pages

02 - Observer Pattern

The document discusses the implementation of the Observer Pattern in a weather monitoring application, detailing the roles of the WeatherData class, observers, and display elements. It emphasizes the importance of loose coupling between subjects and observers, allowing for flexibility and scalability in the system. The document also outlines the design and coding of various display elements that respond to changes in weather data, while highlighting potential issues and solutions in the implementation process.

Uploaded by

Batuhan Ekinci
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/ 39

BIM492 DESIGN PATTERNS

02. OBSERVER PATTERN

Keep your Objects in the know


Don’t miss out when
something interesting happens
Congrats!
Your team has just won the contract to build
Weather-O-Rama, Inc.’s next generation, Internet-
based Weather Monitoring Station.

2
The Weather Monitoring application overview
Players of the system
1. The weather station (physical device acquiring actual weather data)
2. The WeatherData object (tracks data coming from Weather Station and updates displays)
3. Display (shows current weather conditions)

OUR JOB
is to create an app that
uses WeatherData object
to update three displays
for current conditions,
weather stats, and a
forecast.

3
Unpacking the WeatherData class
Our job is to implement
WeatherData source files look pretty straightforward measurementsChanged() method so
that it updates three displays for
current conditions

4
What do we know so far?
 The WeatherData class has getter methods for three measurement values:
temperature, humidity, and barometric pressure

 The measurementsChanged() method is called any time new weather


measurement data is available (We don’t know or care how this method is
called; we just know it is.)

 We need to implement three display elements that use weather data and they
must be updated each time WeatherData has new measurements.

 The system must be expandable


 other developers can create new custom display elements
 users can add/remove as many display elements they want

5
Taking a first, misguided SWAG at Weather Station
Here is a first
public class WeatherData { implementation
// instance variable declarations
possibility
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 WeatherData methods here
}

6
Sharpen your pencil
Based on our first implementation, which of the following apply? (Choose all that apply)
A. We are coding to concrete implementations, not interfaces.
B. For every new display element we need to alter code.
C. We have no way to add (or remove) display elements at run time.
D. The display elements don’t implement a common interface.
E. We haven’t encapsulated the part that changes.
F. We are violating encapsulation of the WeatherData class.

WHAT’S WRONG WITH OUR


IMPLEMENTATION?

7
What’s wrong?
Think back all concepts and principles we covered up till now…

We’ll take a look at


Observer, then come
back and figure out
how to apply it to
the weather app.
8
Meet the Observer Pattern

You know how newspaper or magazine subscriptions work:


1. A newspaper publisher goes into business and begins publishing
newspapers.
2. You subscribe to a particular Publisher, and every time there’s a
new edition it gets delivered to you. As long as you remain a
subscriber, you get new newspapers.
3. You unsubscribe when you don’t want papers anymore, and they
stop being delivered.
4. While the Publisher remains in business, people, hotels, airlines
and other business constantly subscribe and unsubscribe to the
newspaper.

9
Publishers + Subscribers = Observer Pattern
If you understand newspaper
subscriptions, you pretty
much understand the
Observer Pattern.

Only, we call the publisher the


SUBJECT and the
subscribers the
OBSERVERS.

10
A day in the life of the Observer Pattern
A Duck object comes The Mouse object asks to be removed as
along and tells the an observer.
Subject that it wants The Mouse object has been getting ints for ages
to become an observer. and is tired of it, so it decides it’s time to stop
Duck really wants in on the being an observer.
action; those ints Subject
is sending out whenever its
state changes look pretty
interesting...
Mouse is outta here!
The Duck object is now an official The Subject acknowledges the Mouse’s
observer. request and removes it from the set of
Duck is psyched... he’s on the list and is observers.
waiting with great anticipation for the next
notification so he can get an int.

The Subject gets a new data The Subject has another new int.
value! All the observers get another
Now Duck and all the rest of the notification, except for the Mouse who
observers get a notification that is no longer included. Don’t tell anyone,
the Subject has changed. but the Mouse secretly misses those
ints... maybe it’ll ask to be an observer
again some day.

11
Five minute drama: a subject for observation

12
13
Two weeks later…
But what has become of our dear Ron? We hear
he’s beating the headhunter at his own game.
He’s not only still an observer, he’s got his own
call list now, and he is notifying his own observers.
Ron’s a subject and an observer all in one.

Jill’s loving life, and no longer an observer.


She’s also enjoying the nice fat signing
bonus that she got because the company
didn’t have to pay a headhunter.

14
The Observer Pattern defined
A newspaper subscription service with a Publisher and Subscribers is a good way to visualize the pattern.

? HOW AM I GONNA IMPLEMENT


THE OBSERVER PATTERN
15
The Observer Pattern defined: the class diagram

16
there are no
Dumb Questions
Q: What does this have to do with one-to-many Q: How does dependence come to this?
relationships? A: Because the subject is the sole owner of that
A: With the Observer Pattern, the Subject is the data, the observers are dependent on the subject to
object that contains the state and controls it. So, update them when the data changes. This leads to a
there is ONE subject with state. The observers, on cleaner OO design than allowing many objects to
the other hand, use the state, even if they don’t control the same data.
own it. There are many observers and they rely on
the Subject to tell them when its state changes.
So there is a relationship between the ONE Subject
to MANY Observers.

17
The power of Loose Coupling
When two objects are loosely coupled, they can interact, but have very little knowledge of each other.
The Observer Pattern provides an object design where subjects and observers are loosely coupled.
Why?
 The only thing the subject knows about an observer is that it implements a certain interface
 does not need to know about concrete class of the observer, what it does, or anything else
 We can add new observers at any time
 actually we can also remove and even replace observers at runtime
 We never need to modify the subject to add new types of observers
 a new class type of observers just needs to implement the Observer interface and that’s it!
 the subject doesn’t care; it will deliver notifications to any object implementing the Observer interface
 We can reuse subjects or observers independently of each other
 if we have another use for a subject or an observer, it’s no problem. They are not tightly coupled
 Changes to either the subject or an observer will not affect each other
 as long as they implement Subject or Observer interfaces

18
LOOSELY COUPLED DESIGNS ALLOW US TO BUILD FLEXIBLE OO
SYSTEMS THAT CAN HANDLE CHANGE BECAUSE THEY MINIMIZE THE
INTERDEPENDENCY BETWEEN OBJECTS

19
Liabilities of The Observer Pattern
 Possible cascading of notifications
 Simple update iinterface requires observers to deduce changed item

20
Sharpen your pencil

While having a coffee break, try sketching out the classes you’ll need to
implement the Weather Station, including the WeatherData class and its
display elements.

Make sure your diagram shows how all the pieces fit together and also how
another developer might implement her own display element.

21
Designing the Weather Station
How does this
diagram compare
with yours?

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

Measurements are passed directly to the


public interface DisplayElement { observers. Do you think it is wise? Can you
public void display();
think of other ways?
}

Hint: is this an area that might change in


the future?
23
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature; Implementing the Subject Interface
private float humidity;
private float pressure;
public WeatherData() {
Remember our first attempt at
observers = new ArrayList(); implementing the WeatherData
}
public void registerObserver(Observer o) { class at the beginning of the
}
observers.add(o);
class? You might want to
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
refresh your memory.
if (i >= 0) { observers.remove(i); } public class WeatherData {
} // instance variable declarations
public void measurementsChanged() {
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) { float temp = getTemperature();
Observer observer = (Observer)observers.get(i); float humidity = getHumidity();
float pressure = getPressure();
observer.update(temperature, humidity, pressure);
} currentConditionsDisplay.update(temp, humidity, pressure);
} statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
public void measurementsChanged() { }
notifyObservers(); // other WeatherData methods here
} }
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
} // other WeatherData methods here
} 24
Now, let’s build those
display elements Let’s take a look at the current
conditions display; once you
have a good feel for this
public class CurrentConditionsDisplay implements Observer, DisplayElement { display element, you can
private float temperature; implement other displays.
private float humidity;
there are no
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
Dumb Questions
this.weatherData = weatherData; Q: Is Update() the best
weatherData.registerObserver(this); place to display?
} A: In this example it made sense
public void update(float temperature, float humidity, float pressure) { to call display() when the
this.temperature = temperature; values changed. However, we are
this.humidity = humidity; going to see this when we get
display(); to MVC pattern.
}
public void display() { Q: Why did you store a
System.out.println(“Current conditions: “ + temperature + reference to the Subject? It
“F degrees and “ + humidity + “% humidity”); doesn’t look like you use it
} again after the constructor?
} A: True, but in the future we
may want to un-register as an
observer and it would be handy.
25
Other two displays
public void update(float temp, float humidity, float pressure) {
tempSum += temp; numReadings++;
Implementations of update and display
if (temp > maxTemp) { methods regarding avg/max/min and
maxTemp = temp;
} forecast displays are as follows:
if (temp < minTemp) {
minTemp = temp;
}
display();
}
public void display() {
System.out.println("Avg/Max/Min temperature = " +
(tempSum / numReadings) + "/" + maxTemp + "/" + minTemp); } Forecast Display
Avg/Max/Min Display public void update(float temp, float humidity, float pressure) {
lastPressure = currentPressure;
currentPressure = pressure;
display();
}
public void display() {
System.out.print("Forecast: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
else if (currentPressure == lastPressure) {
System.out.println("More of the same");
else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
} 26
Power up the Weather Station
2. Run the code

1. First, let’s create a harness


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);
}
}
27
Sharpen your pencil
Weather-O-Rama’s CEO just called, they can’t possibly ship without a Heat Index display element.
It is calculated like this given temperature T, and relative humidity RH.

Now create your HeatIndexDisplay.java file.


When you finish, your output should look like this:

28
Just for your record _ HeatIndexDisplay.java
public class HeatIndexDisplay implements Observer, DisplayElement {
float heatIndex = 0.0f;
private WeatherData weatherData;
public HeatIndexDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float t, float rh, float pressure) {
heatIndex = computeHeatIndex(t, rh);
display();
}
private float computeHeatIndex(float t, float rh) {
float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh) +
(0.00941695 * (t * t)) + (0.00728898 * (rh * rh)) + (0.000345372 * (t * t * rh)) –
(0.000814971 * (t * rh * rh)) + (0.0000102102 * (t * t * rh * rh)) –
(0.000038646 * (t * t * t)) + (0.0000291583 * (rh * rh * rh)) +
(0.00000142721 * (t * t * t * rh)) + (0.000000197483 * (t * rh * rh * rh)) –
(0.0000000218429 * (t * t * t * rh * rh)) + 0.000000000843296 * (t * t * rh * rh * rh)) –
(0.0000000000481975 * (t * t * t * rh * rh * rh)));
return index;
}
public void display() {
System.out.println("Heat index is " + heatIndex);
}
} 29
Tonight’s talk: A subject and Observer spar over the right way to
Fireside Chats get state information to the Observer.
Subject: I'm glad we're finally getting a chance to chat in Ok, wait just a minute here; first, we're not lazy, we just
person. have other stuff to do in between your oh-so-important
Object: Really? I thought you didn't care much about us notifications, Mr. Subject, and second, why don't you let
Observers. us come to you for the state we want rather than pushing
Well, I do my job, don't I? I always tell you what's going it out to just everyone?
on... Just because I don't really know who you are doesn't
mean I don't care. And besides, I do know the most
important thing about you—you implement the Observer
interface. Well... I guess that might work. I'd have to open myself up
Well yeah, but that's just a small part of who I am. even more though to let all you observers come in and get
Anyway, I know a lot more about you... the state that you need. That might be kind of dangerous. I
Oh yeah, like what? can't let you come in and just snoop around looking at
everything I've got.
Well, you're always passing your state around to us
Observers so we can see what's going on inside you. Which
gets a little annoying at times...
Why don't you just write some public getter methods that
Well excuuuse me. I have to send my state with my
notifications so all you lazy Observers will know what will let us pull out the state we need?
happened!

30
Tonight’s talk: A subject and Observer spar over the right way to
Fireside Chats get state information to the Observer.
Subject: Yes, I could let you pull my state. But won't that Well, I can see the advantages to doing it both ways. I have
be less convenient for you? If you have to come to me noticed that there is a built-in Java Observer Pattern that
every time you want something, you might have to make allows you to use either push or pull.
multiple method calls to get all the state you want. That's
why I like push better... then you have everything you need
in one notification. Oh really? I think we're going to look at that next....

Object: Don't be so pushy! There's so many different Great... maybe I'll get to see a good example of pull and
kinds of us Observers, there's no way you can anticipate change my mind.
everything we need. Just let us come to you to get the
state we need. That way, if some of us only need a little
bit of state, we aren't forced to get it all. It also makes What, us agree on something? I guess there's always hope.
things easier to modify later. Say, for example, you expand
yourself and add some more state, well if you use pull, you
don't have to go around and change the update calls on
every observer, you just need to change yourself to allow
more getter methods to access our additional state.
31
Using Java’s built-in Observer Pattern

32
How Java’s built-in Observer Pattern works
The most obvious difference from our implementation is WeatherData (our subject) now extends Observable
class and inherits add, delete, and notify Observer (among a few others) methods. Here’s how we use it:
 For an Object to become an observer… If you want to "push" data to
 implement Observer interface (like before but this time java.util.Observer interface) the observers you can pass
 call addObserver() on any Observable object the data as a data object to
the
 Call deleteObserver() to un-register
notifyObserver(arg)
 For the Observable to send notifications… method.
 First, you need to be Observable by extending java.util.Observer
1. Call setChanged() to signify the state has changed in your object If not, then the Observer has
2. Then call one of two notifyObservers() methods to "pull" the data
either notifyObservers() or notifyObservers(Object arg) it wants from the Observable
object passed to it.
 For an Observer to receive notifications…
 it implements update method, as before, but with a different signature
Update(Observable o, Object arg)

How?
Let's rework the Weather
Station and you'll see.
33
Question marks in your mind?
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 our 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.

34
Reworking the Weather Station with the built-in support First let’s rework
"WeatherData" to use
java.util.Observable

35
Now let’s rework the CurrentConditions Display

36
Running the new code __ just to be sure
Never depend on order of evaluation of the
Observer notifications!
The java.util.Observable has implemented its
notifyObservers() method such that the Observers are
notified in a different order than our own implementation. Who's
right? Neither; we just chose to implement things in different
ways.

What would be incorrect, however, is if we wrote our code to


depend on a specific notification order.

Why? Because if you need to change Observable/Observer


? Do you notice anything different? Look again.. implementations, the order of notification could change and your
application would produce incorrect results.
 The order of the text output is different.
 Why might this happen? Think for a minute.. Now that's definitely not what we'd consider loosely coupled.

37
Program to an interface not an implementation.
/)/+)(&+Program to an interface not an implementation.+=(+=(/
+=)()=(Program to an interface not an implementation.+)+=(+/
^=)(+)(+Program to an interface not an implementation.+/()/^)/+
+=)(+=Program to an interface not an implementation. ??=(+(%

 Yes, good catch.


 and worse, it doesn't even implement an interface.
Observable is a class
 First, because Observable is a class, you have to subclass it. That means you can't add the
Observable behavior to an existing class that already extends another superclass. This limits
its reuse potential (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.
Observable protects crucial methods
 setChanged() method is protected. So what?
 This means you can't call setChanged() unless you've subclassed Observable.
 You can't even create an instance of the Observable class and compose it with your own
objects, you have to subclass. The design violates a second design principle here...
favor composition over inheritance.
What to do?
The dark side of  Observable may serve your needs if you can extend java.util.Observable. On the
java.util.Observable other hand, you may need to roll your own implementation as we did at the beginning of the
class.

38
Tools for your Design Toolbox
Let’s look at the tools you’ve put in your OO toolbox.
Bullet Points
 The observer Pattern defines a one-to-many
relationship between objects.
 Subjects, or observables, update Observers using a
common interface.
 Observers are loosely coupled
 You can push or pull data from the Observable
 Don’t depend on a specific "order of notification"
 Java has several implementations of Observer Pattern
 Swing makes heavy use as do many GUI frameworks
 Don’t be afraid to create your own Observable
implementation

39

You might also like