Observer Pattern

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.

Observer pattern diagram

Implementation

Creating Subject interface:

public interface Subject {
	public void registerObserver(Observer o);
	public void removeObserver(Observer o);
	public void notifyObservers();
}

Create Observer interface:

public interface Observer {
	public void update();
}

Create another role that observer implements:

public interface DisplayElement {
	public void display();
}

Creating Concrete Subject:

public class WeatherData implements Subject {
	private List<Observer> observers;
	private float temparature;
	private float humidity;
	private float pressure;
	
	public WeatherData() {
		observers = new ArrayList<Observer>();
	}
	
	/* Observers have reference to this subject.
	Thus, they can register or deregister itself by calling these methods */
	
	public void registerObserver(Observer o) {
		observers.add(o);
	}
	
	public void removeObserver(Observer o) {
		observers.remove(o);
	}
	
	public void notifyObservers() {
		for (Observer observer : observers) {
			observer.update();
		}
	}
	
	public void measurementsChanged() {
		notifyObservers();
	}
	
	public void setMeasurements(float temparature, float humidity, float pressure) {
		this.temparature = temparature;
		this.humidity = humidity;
		this.pressure = pressure;
		measurementsChanged();
	}
	
	public float getTemperature() {
		return this.temparature;
	}
	
	public float getHumidity() {
		return this.humidity;
	}
	
	public float getPressure() {
		return this.pressure;
	}
}

Creating a Concrete Observer:

public class CurrentConditionsDisplay implements Observer, DisplayElement{
	private float temparature;
	private float humidity;
	private WeatherData weatherData;
	
	public CurrentConditionsDisplay(WeatherData weatherData) {
		this.weatherData = weatherData;
		weatherData.registerObserver(this);
	}
	  
	/* Pull */	
	public void update() {
		this.temparature = weatherData.getTemperature();
		this.humidity = weatherData.getHumidity();
		display();
	}
	
	public void display() {
		System.out.println("Current conditions: " + temparature + "F degrees and " + humidity + "% humidity");
	}
}

Testing:

public class WeatherStation {
	public static void main(String[] args) {
	
	/* Subject */
	WeatherData weatherData = new WeatherData();
	
	/* Observers */
	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);
 
	}
}