Observer Pattern

From REALbasicWiki

Jump to: navigation, search

Contents

[edit] Intention

An Observer Pattern defines a one-to-many relationship between a set of objects. When the state of one object changes, all of its dependents are notified.

[edit] Class-Diagram

Image:Observer.png

[edit] Example

The following example shows the Observer Pattern in REALbasic. It was inspired by an example in the book Head First Design Patterns from O'Reilly. Although the examples there are coded in JAVA it is a very good book for RB-programmers too.

Imagine we have a weatherstation that produces data for electronic weather-devices. Each time the weather-conditions change we want our devices to update automatically. To achieve this we implement the Observer Pattern.

First of all we define the Subject-Interface with its three methods notifyObservers(), registerObserver(), removeObserver() The registerObserver-method lets a new Observer register to the Subject. In the case the Observer doesn't want to get notified any longer it needs a way to unregister from the Subject. This is done via the removeObserver-method. When the state of the Subject changes and it wants its Observers to know about that the notifyObservers-method is called that signals all Observers that the Subject has changed its state. If the Observers react to this notification or not depends on themselves.


Interface Subject

Sub notifyObservers()
End Sub

Sub registerObserver(o as Observer)
End Sub

Sub removeObserver(o as Observer)
End Sub

End Interface


Then we define the Observer-Interface. Each object that wants to be notified of any changes of the Subject has to register to it. When the Subjects method notifyObservers is called, the Subject calls the method update() for every Observer it has in its internal list.


Interface Observer

Sub update(t as double, h as double, p as double)
End Sub

End Interface


Now lets take a look on our Subject. For our example the Subject is a class that provides data about weatherconditions. This class has three weather-related properties: humidity, pressure and temperature. It also has an array of type Observer in which all its observers are stored. Each time a new Observer registers via the registerObserver() method, its reference is added to the observers-array. When the measurements change the the WeatherData class informs its Observers that it has changed its state.


Class WeatherData Implements Subject

Sub measurementsChanged()
notifyObservers
End Sub

Sub notifyObservers()
for each o as Observer in observers
o.update(temperature, humidity, pressure)
next
End Sub

Sub registerObserver(o as Observer)
observers.Append o
End Sub

Sub removeObserver(o as Observer)
observers.Remove observers.IndexOf(o)
End Sub

Sub setMeasurements(t as double, h as double, p as double)
self.temperature = t
self.humidity = h
self.pressure = p
measurementsChanged
End Sub

Private humidity As double
Private observers() As Observer
Private pressure As double
Private temperature As double

End Class

Lets create a device that makes use of the data provided by Weatherdata. What about a display that shows us the current weather conditions?


Class CurrentConditionsDisplay Implements Observer

Sub Constructor(s as Subject)
self.weatherData = s
weatherData.registerObserver(self)
End Sub

Sub display()
Msgbox "Current conditions: " + str(temperature) + "F degrees and " + _
str(humidity) + "% humidity"
End Sub

Sub update(t as double, h as double, p as double)
self.temperature = t
self.humidity = h
display
End Sub

Private humidity As double
Private temperature As double
Private weatherData As Subject

End Class

As you can see the CurrentConditionsDisplay implements the update() method from the Observer-interface. Each time the Subjects notifyObservers()-method is called this method will be started.

What about a second observer? Hmmm... lets create a statistic-device that stores weather-data for analysis.


Class StatisticsDisplay Implements Observer

Sub Constructor(s as Subject)
self.weatherData = s
weatherData.registerObserver(self)
End Sub

Sub display()
dim t as string = "Statistics" + endofline + _
"Temperature/Humidity/Pressure" + endofline

for i as integer = 0 to ubound(temperature)
t = t + str(temperature(i)) + "/" + str(humidity(i)) + "/" + str(pressure(i)) _
+ endofline
next

msgbox t

End Sub

Sub update(t as double, h as double, p as double)
self.temperature.Append t
self.humidity.Append h
self.pressure.Append p
display
End Sub

Private humidity() As double
Private pressure() As double
Private temperature() As double
Private weatherData As Subject

End Class

Lets try it out:


dim weatherData as new WeatherData
dim currentDisplay as new CurrentConditionsDisplay(WeatherData)
dim statisticsDisplay as new StatisticsDisplay(WeatherData)

weatherData.setMeasurements(80, 65, 30.4)
weatherData.setMeasurements(82, 70, 29.2)
weatherData.setMeasurements(78, 90, 29.3)

Each time the setMeasurement()-method is called each observer is notified and will fire a messagebox.

[edit] External resources

http://en.wikipedia.org/wiki/Observer_pattern

For more information about the Unified Modeling Language that was used to describe the classes please visit these links:

http://www.holub.com/goodies/uml/index.html

http://www.developer.com/design/article.php/2206791

http://en.wikipedia.org/wiki/Unified_Modeling_Language

Personal tools
related