56
Observer Pattern Steven R. Bagley

Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

  • Upload
    others

  • View
    22

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Observer PatternSteven R. Bagley

Page 2: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Introduction

• Another new pattern

• Already seen

• Strategy

• Decorator

• The Observer Pattern

Page 3: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Weather Monitoring

SCI showed how weather information could be transmitted

Page 4: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Weather Station

• Various sensors recording

• Temperature

• Pressure

• Humidity

• Periodically send data to central computer

• Need software to handle data

See SCI for details of how you might encode the data…

Page 5: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Software

• Clients want three displays

• Current data

• Statistics

• Forecast

• Displays must update automatically

Page 6: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Break into objects

• Object to represent the weather station

• Handles receiving data from sensors

• Accessor methods to get data

• Ignore hardware side, assume object always returns latest live data

• Displays can call methods to get data

We are not interested in how the data is fetched -- probably the object creates a thread that talks to the hardware or sets up interrupt handlers. Irrelevant for this discussion.

Page 7: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Display

• Class for each display

• Each Class has a reference to the WeatherStation object

• Display gets data from the WeatherStation object

• The question is when…

Page 8: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

GetTemperature()GetPressure()GetHumidity()

// other methods

WeatherStationDisplay()weatherStationForecastDisplay

Display()weatherStationStatisticsDisplay

Display()weatherStationCurrentDataDisplay

Page 9: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Updates

• Current Data Display is easy, regularly refresh display

• Statistics and Forecast more tricky

• Data could be updated at any point

• If any is missed then the statistics aren’t correct and the forecast less accurate

Page 10: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Polling

• Forecast and Stats. Display objects will need to poll continuously

• Use a lot of CPU time

• Inefficient

• How can we tell the data is new?

Page 11: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Push or Pull

• This is a pull model

• We ‘pull’ the data from the WeatherStation object when we need it

• No way of knowing if and when it has changed

Page 12: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Push Model

• Only thing that knows that the data has changed is WeatherStation

• Turn things around

• Rather than the displays polling WeatherStation

• WeatherStation tells the displays that things have changed

Page 13: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

GetTemperature()GetPressure()GetHumidity()

MeasurementsChanged()

// other methods

WeatherStationDisplay()Update()

ForecastDisplay

Display()Update()

StatisticsDisplay

Display()Update()

CurrentDataDisplay

Page 14: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Changes

• WeatherStation now has references to displays

• New MeasurementsChanged method

• Called internally whenever new values received from the sensors

• Dispatches messages to the display objects

Page 15: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

classs CWeatherStation{public:double GetTemperature();double GetPressure();double GetHumidity();

private:void MeasurementsChanged();

/* various other methods */};

Page 16: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

void CWeatherStation::MeasurementsChanged();{double t = GetTemperature();double h = GetHumiditiy();double p = GetPressure();

m_currentConditionsDisplay->Update(t, h, p);m_statisticsDisplay->Update(t, h, p);m_forecastDisplay->Update(t, h, p);}

Page 17: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

void CWeatherStation::MeasurementsChanged();{double t = GetTemperature();double h = GetHumiditiy();double p = GetPressure();

m_currentConditionsDisplay->Update(t, h, p);m_statisticsDisplay->Update(t, h, p);m_forecastDisplay->Update(t, h, p);}

Coding to concrete implementation what if

we need to change it

Page 18: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

void CWeatherStation::MeasurementsChanged();{double t = GetTemperature();double h = GetHumiditiy();double p = GetPressure();

m_currentConditionsDisplay->Update(t, h, p);m_statisticsDisplay->Update(t, h, p);m_forecastDisplay->Update(t, h, p);} {At least we seem to be

using a common interfaceCoding to concrete implementation what if

we need to change it

Page 19: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

How are we doing?

• Better solution — removes the need for displays to poll WeatherStation

• Tied to a specific set of displays

• How do we add/remove displays without recompile?

• Could we use a Strategy Pattern here?

Strategy not really appropriate, the behaviour isn’t really changing, it’s just who is being notified that changes. We don’t want a class explosion for each different group of objects that might be listening.

Page 20: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Newspapers are published and people can opt into having them delivered to them and at a later time stopThe Observer pattern works in the same model the subject being observed has a group of subscribers that it ‘publishes’ the information too.

Page 21: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Here is the news…

• The WeatherStation has information it wants to share

• But it does not need to know who it is giving it to

• Need a mechanism that allows WeatherStation to publish the information to whoever is listening for it

Page 22: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Observer Pattern

• Identical to newspaper delivery (minus the paper boy)

• Object publishing the information is called the Subject

• Objects subscribing to the information are called Observers

Page 23: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Bagpuss

Bagpuss subject sends information out, received by Charlie, Lizzie and EddieYaffle doesn’t get it (he’s not registered to receive it)

Page 24: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

Bagpuss

Bagpuss subject sends information out, received by Charlie, Lizzie and EddieYaffle doesn’t get it (he’s not registered to receive it)

Page 25: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

Yaffle

Bagpuss

Bagpuss subject sends information out, received by Charlie, Lizzie and EddieYaffle doesn’t get it (he’s not registered to receive it)

Page 26: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

Yaffle

Bagpuss

Bagpuss subject sends information out, received by Charlie, Lizzie and EddieYaffle doesn’t get it (he’s not registered to receive it)

Page 27: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

Yaffle

Bagpuss

Yaffle decides he wants in on the action so registers himself with BagpussBagpuss sends out new data which they all receiveEddie’s fed up with the data so unregisters himselfBagpuss then sends out more datawhich Eddie doesn’t receive

Page 28: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

YaffleBagpuss

Yaffle decides he wants in on the action so registers himself with BagpussBagpuss sends out new data which they all receiveEddie’s fed up with the data so unregisters himselfBagpuss then sends out more datawhich Eddie doesn’t receive

Page 29: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

YaffleBagpuss

Yaffle decides he wants in on the action so registers himself with BagpussBagpuss sends out new data which they all receiveEddie’s fed up with the data so unregisters himselfBagpuss then sends out more datawhich Eddie doesn’t receive

Page 30: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

YaffleBagpuss

Yaffle decides he wants in on the action so registers himself with BagpussBagpuss sends out new data which they all receiveEddie’s fed up with the data so unregisters himselfBagpuss then sends out more datawhich Eddie doesn’t receive

Page 31: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

YaffleBagpuss

Yaffle decides he wants in on the action so registers himself with BagpussBagpuss sends out new data which they all receiveEddie’s fed up with the data so unregisters himselfBagpuss then sends out more datawhich Eddie doesn’t receive

Page 32: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Observer Pattern

• Observer defined

• 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

Page 33: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

2

2

2

YaffleBagpuss

2

Page 34: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

2

2

2

YaffleBagpuss

2

Objectholding state

Page 35: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

2

2

2

YaffleBagpuss

2

Objectholding state

One-to-many Relationship

Page 36: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

2

2

2

YaffleBagpuss

2

Dependentobjects

Objectholding state

One-to-many Relationship

Page 37: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Charlie

Lizzie

Eddie

2

2

2

YaffleBagpuss

2

Automaticupdate

Dependentobjects

Objectholding state

One-to-many Relationship

Page 38: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Observer defined

• One-to-Many

• One object holds the data – the Subject

• Many recipients — the Observers

• Observers dependent on the Subject to inform them of changes in the data

Page 39: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

RegisterObserver()RemoveObserver()NotifyObserver()

<<interface>>Subject

RegisterObserver()RemoveObserver()NotifyObserver()

GetState()SetState()

ConcreteSubject

Update()

<<interface>>Observer

Update()

// other Observer Specific methods

ConcreteObserver

*

1

Page 40: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Loose Coupling

• Loose Coupled objects interact, but have little knowledge of each other

• Observer Pattern is an example of a loosely coupled OO design

Page 41: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Loose Observation

• Subject only knows that Observers implement an interface

• Can add new observers at any point

• New observer types don’t need modification of the Subject

• Changes to subject or observer don’t affect the other

Page 42: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Design Principle

“Strive for loosely coupled designs between objects that interact.”

Page 43: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Weather Observation

• WeatherStation has the state that’s changing so we make this the subject

• Displays need to be notified, so we make each of these observers

• Give displays an Update() method that gets called with the data as parameters

Page 44: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

RegisterObserver()RemoveObserver()NotifyObserver()

<<interface>>Subject

RegisterObserver()RemoveObserver()NotifyObserver()

GetTemperature()GetHumidity()GetPressure()MeasurementsChanged()

WeatherStation

Update()

<<interface>>Observer

*

1

Display()

<<interface>>Window

Update()Display()

CalculateForecast()

ForecastDisplay

Update()Display()

CurrentConditionsDisplay

Update()Display()

StatisticsDisplay

Page 45: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Weather Station App

• Create WeatherStation object

• Create the display objects

• Register the display objects with WeatherStation object

Page 46: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Implementing Subject

• How do we implement the Subject?

• Need to manage a collection of objects

• Arrays unsuitable — Fixed Size, need to shift values around

• Linked List better choice

• Example here will use an array for simplicity

Page 47: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

classs CWeatherStation : public ISubject{public: void RegisterObserver(IObserver *o); void RemoveObserver(IObserver *o); void NotifyObservers(); double GetTemperature(); double GetPressure(); double GetHumidity();

private: void MeasurementsChanged();

IObserver *m_observers[10]; int m_cObservers;};

Page 48: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

class IObserver{public: virtual void Update(double temperature, double humidity, double pressure) = 0;}

Page 49: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Registering Observers

• Simple

• Add the observer to the list

• Probably should check it is not in the list already

Page 50: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

void CWeatherStation::RegisterObserver(IObserver *o){ if(o != NULL && m_cObservers < 9) { m_observers[m_cObservers++] = o; }}

Page 51: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Notify Observers

• Again, simple

• Step through the list calling each observer’s update method

Page 52: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Remove Observer

• Slightly more complicated

• Need to find node (if present) containing the observer

• Then Delete it from the list

Page 53: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Observer Update

• What about Update()?

• Update the display status

• Call Display() method to redraw the screen

Page 54: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Push Data or Pull Data

• Our WeatherStation is pushing the data at the objects with the notification that it has changed

• Would it be better to notify the observer and let it pull what it needs?

• It depends

Page 55: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Amount of State

• In our example the amount of state is tiny and so it does make sense to push it

• If however there is a lot of state to pass over then it is probably best to just notify that it has changed

• Observer can then get what it needs

Page 56: Observer Pattern - eprg.org · Observer Pattern • Observer defined • The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state,

Summary

• Observer Pattern

• A one-to-many relationship

• Where a subject notifies many observers that it’s state has changed