Observer Pattern
Part 3
Java Built-in Observer Pattern
Java Built-in Observer
Pattern
• Java has several built-in observer pattern
• The general one exist in the util package
• java.util
• Subject/Observable: java.util.Observable
• http://developer.classpath.org/doc/java/util/Observable-source.html
• Observer: java.util.Observer
• http://developer.classpath.org/doc/java/util/Observer-source.html
• They are similar to our Subject & Observer, but give a lot of already built-in
functionalities
• In the observer you can choose push or pull for the update
Weather app Using Java-
built-in observer pattern
• Java built-in Observer is exactly as our observer
• Observable is class not interface like the Subject
• setChanged() didn’t exist in our Subject
Concrete Subject (WeatherData)
Using Java Built-in Observable
import java.util.Observable;
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public WeatherData() { }
• import the Observable
public void measurementsChanged() {
setChanged();
• The concrete Subject extends notifyObservers();}
the Observable (it is a class) public void setMeasurements(float temperature,
float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();}
//getter methods
}
Concrete Subject (WeatherData)
Using Java Built-in Observable
import java.util.Observable;
• No need to keep a list of public class WeatherData extends Observable {
private float temperature;
observers
private float humidity;
private float pressure;
• The constructor doesn’t need public WeatherData() { }
to create a data structure to
public void measurementsChanged() {
manage observers
setChanged();
notifyObservers();}
• The super class (Observable)
public void setMeasurements(float temperature,
will handle that
float humidity, float pressure) {
this.temperature = temperature;
• This means we don’t need to
this.humidity = humidity;
this.pressure = pressure;
manage addition/removal of measurementsChanged();}
observers //getter methods
}
Concrete Subject (WeatherData)
Using Java Built-in Observable
import java.util.Observable;
public class WeatherData extends Observable {
private float temperature;
• Java Observable has private float humidity;
setChanged() method to indicate private float pressure;
that there is a change, so we call public WeatherData() { }
this method first
public void measurementsChanged() {
setChanged();
• Then, call the notifyObserver()
notifyObservers();}
• Both setChanged and public void setMeasurements(float temperature,
float humidity, float pressure) {
notifyObservers methods are this.temperature = temperature;
inherited from the Observable this.humidity = humidity;
class this.pressure = pressure;
measurementsChanged();}
//getter methods
}
Concrete Subject (WeatherData)
Using Java Built-in Observable
import java.util.Observable;
• Then, call the notifyObserver()
public class WeatherData extends Observable {
private float temperature;
private float humidity;
• There are two option to notify private float pressure;
observers
public WeatherData() { }
• as in the example (PULL), public void measurementsChanged() {
details of change will not be setChanged();
notifyObservers();}
sent to the observer
public void setMeasurements(float temperature,
• No arguments sent by the float humidity, float pressure) {
notify method
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
• notifyObservers(args ..) measurementsChanged();}
(PUSH) //getter methods
}
Concrete Observer (Display)
Using Java Built-in Observer
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements
Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity;
• Implement the Observer public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
interface from java.util
observable.addObserver(this);}
• same as old implementation public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData) obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();}}
//display method here
}
Concrete Observer (Display)
Using Java Built-in Observer
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements
Observer, DisplayElement {
• The java.util Observable is
Observable observable;
private float temperature;
passed to the constructor
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
• In the old implementation, we this.observable = observable;
passed the Concrete subject observable.addObserver(this);}
(WeatherData) to the public void update(Observable obs, Object arg) {
constructor
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData) obs;
• why? this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();}}
//display method here
}
Concrete Observer (Display)
Using Java Built-in Observer
import java.util.Observable;
import java.util.Observer;
• The update() takes two public class CurrentConditionsDisplay implements
Observer, DisplayElement {
parameters; Observable & and Observable observable;
optional data argument
private float temperature;
private float humidity;
• Make sure that the observable public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
is of type WeatherData
observable.addObserver(this);}
• Use the getter methods in the public void update(Observable obs, Object arg) {
WeatherData to get the if (obs instanceof WeatherData) {
variables values
WeatherData weatherData = (WeatherData) obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
• Finally, call display() display();}}
//display method here
}
Notes on the Java built-in
Observable class
• Defined as a class
• The internal implementation to keep a collection of
observers is different than we did in our own
implementation
• We used ArrayList: this means when we send notification,
the notification will be sent in order
• This is not the case for the built-in Observable
Issues with the Java built-in
Observable class
• It violates the OO design principle of programming to
interfaces not implementations
• Observable is not interface and doesn’t even implement
an interface
• This limits its reuse
• It is a class, the only way to use it is by sub classing it
• This means we can’t easily add behaviors
Issues with the Java built-in
Observable class
protected synchronized void setChanged()
{
changed = true;
• Observable protects its crucial }
methods
• What do you think of this?
• Which principle is violated?
Issues with the Java built-in
Observable class
• Observable protects its crucial
methods
protected synchronized void setChanged()
{
• The only way to use changed = true;
setChanged method is by }
subclassing it
• We can’t make an instance of
the Observable and compose it
with our object, we have to
subclass it
• Violate favor composition over
inheritance