Tuesday, May 4, 2010

Observer Pattern

The observer pattern is a behavioral object design pattern. In the observer pattern, an object called the subject maintains a collection of objects called observers. When the subject changes, it notifies the observers. Observers can be added or removed from the collection of observers in the subject. The changes in state of the subject can be passed to the observers so that the observers can change their own state to reflect this change.
The subject has an interface that defines methods for attaching and detaching observers from the subject's collection of observers. This interface also features a notification method. This method should be called when the state of the subject changes. This notifies the observers that the subject's state has changed. The observers have an interface with a method to update the observer. This update method is called for each observer in the subject's notification method. Since this communication occurs via an interface, any concrete observer implementing the observer interface can be updated by the subject. This results in loose coupling between the subject and the observer classes.
Now we'll look at an example of the observer pattern. We'll start by creating an interface for the subject called WeatherSubject. This will declare three methods: addObserver(), removeObserver(), and doNotify().

WeatherSubject.java

package com.cakes;

public interface WeatherSubject {

 public void addObserver(WeatherObserver weatherObserver);

 public void removeObserver(WeatherObserver weatherObserver);

 public void doNotify();

}
We'll also create an interface for the observers called WeatherObserver. It features one method, a doUpdate() method.

WeatherObserver.java

package com.cakes;

public interface WeatherObserver {

 public void doUpdate(int temperature);
 
}
The WeatherStation class implements WeatherSubject. It is our subject class. It maintains a set of WeatherObservers which are added via addObserver() and removed via removeObserver(). When WeatherSubject's state changes via setTemperature(), the doNotify() method is called, which contacts all the WeatherObservers with the temperature via their doUpdate() methods.

WeatherStation.java

package com.cakes;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class WeatherStation implements WeatherSubject {

 Set weatherObservers;
 int temperature;

 public WeatherStation(int temperature) {
  weatherObservers = new HashSet();
  this.temperature = temperature;
 }

 @Override
 public void addObserver(WeatherObserver weatherObserver) {
  weatherObservers.add(weatherObserver);
 }

 @Override
 public void removeObserver(WeatherObserver weatherObserver) {
  weatherObservers.remove(weatherObserver);
 }

 @Override
 public void doNotify() {
  Iterator it = weatherObservers.iterator();
  while (it.hasNext()) {
   WeatherObserver weatherObserver = it.next();
   weatherObserver.doUpdate(temperature);
  }
 }

 public void setTemperature(int newTemperature) {
  System.out.println("\nWeather station setting temperature to " + newTemperature);
  temperature = newTemperature;
  doNotify();
 }

}
WeatherCustomer1 is an observer that implements WeatherObserver. Its doUpdate() method gets the current temperature from the WeatherStation and displays it.

WeatherCustomer1.java

package com.cakes; public class WeatherCustomer1 implements WeatherObserver { @Override public void doUpdate(int temperature) { System.out.println("Weather customer 1 just found out the temperature is:" + temperature); } } WeatherCustomer2 performs similar functionality as WeatherCustomer1.

WeatherCustomer2.java

package com.cakes; public class WeatherCustomer2 implements WeatherObserver { @Override public void doUpdate(int temperature) { System.out.println("Weather customer 2 just found out the temperature is:" + temperature); } } The Demo class demonstrates the observer pattern. It creates a WeatherStation and then a WeatherCustomer1 and a WeatherCustomer2. The two customers are added as observers to the weather station. Then the setTemperature() method of the weather station is called. This changes the state of the weather station and the customers are notified of this temperature update. Next, the WeatherCustomer1 object is removed from the station's collection of observers. Then, the setTemperature() method is called again. This results in the notification of the WeatherCustomer2 object.

Demo.java

package com.cakes; public class Demo { public static void main(String[] args) { WeatherStation weatherStation = new WeatherStation(33); WeatherCustomer1 wc1 = new WeatherCustomer1(); WeatherCustomer2 wc2 = new WeatherCustomer2(); weatherStation.addObserver(wc1); weatherStation.addObserver(wc2); weatherStation.setTemperature(34); weatherStation.removeObserver(wc1); weatherStation.setTemperature(35); } } The console output of executing Demo is shown here.

Console Output

Weather station setting temperature to 34 Weather customer 2 just found out the temperature is:34 Weather customer 1 just found out the temperature is:34 Weather station setting temperature to 35 Weather customer 2 just found out the temperature is:35 In a more advanced case, we might have given each observer a reference to the weather station object. This could allow the observer the ability to compare the state of the subject in detail with its own state and make any necessary updates to its own state.

No comments:

Post a Comment