Design Patterns - Observer Pattern

Observer Pattern-Screen

Intent

According to Gang of Four, the intent of Observer Pattern is to:

Defines a One to Many dependency between objects so that when one object changes State, all of its dependencies are notified and updated automatically.

Problem

You need to notify a varying list of objects that an event has occurred.

Solution

Observers delegate the responsibility for monitoring for an event to a central object Subject

Participants

  • Subject - Object that holds the state of Observer registered with it. It maintains list of it’s dependencies called Observers and notifies them automatically of any state change.

  • Observers - Object are responsible for registering with the Subject and for getting the information from the Subject when notified.

Implementation

Have objects (Observers) that want to know when an event happens attach themselves to another object (Subject) that is watching for the event to occur or that triggers the even itself.

When the event occurs, the Subject tells the Observers that it has occurred.

Observer Pattern

Example

example-observer-design-pattern

CurrentConditionsDisplay.java

package com.art.headfirst.WeatherStationApp.example;

/**
 * Concrete Observer
 *
 * * Responsible for Registering with Subject
 * * Implements Observer Interface
 *
 */
public class CurrentConditionsDisplay implements Observer, DisplayElement {

  private float temperature;
  private float humidity;
  private float pressure;

  public CurrentConditionsDisplay(Subject weatherData) {
    weatherData.registerObserver(this);
  }

  @Override
  public void display() {
    System.out.println("Current Weather Condition:");
    System.out.println("Temperature: " + temperature);
    System.out.println("Humidity: " + humidity);
    System.out.println("Pressure: " + pressure);
  }

  @Override
  public void update(float temp, float humidity, float pressure) {
    this.temperature = temp;
    this.humidity = humidity;
    this.pressure = pressure;
    display();
  }
}

DisplayElement.java

package com.art.headfirst.WeatherStationApp.example;

public interface DisplayElement {
    void display();
}

Observer.java

package com.art.headfirst.WeatherStationApp.example;

public interface Observer {
    void update(float temp, float humidity, float pressure);
}

Subject.java

package com.art.headfirst.WeatherStationApp.example;

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

WeatherData.java

package com.art.headfirst.WeatherStationApp.example;

import java.util.ArrayList;

/**
 * Concrete Subject
 *
 * * Object that maintains list of  Observers
 * * Notifies on Updates
 *
 */
public class WeatherData implements Subject {

  private float temperature;
  private float humidity;
  private float pressure;
  private ArrayList observers;

  public WeatherData() {
    observers = new ArrayList();
  }

  @Override
  public void registerObserver(Observer observer) {
    observers.add(observer);
  }

  @Override
  public void removeObserver(Observer observer) {
    int i = observers.indexOf(observer);

    if (i >= 0) {
      observers.remove(i);
    } else {
      throw new IllegalStateException("Unknown Observer");
    }
  }

  @Override
  public void notifyObservers() {
    observers.forEach(o -> {
      Observer observer = (Observer) o;
      observer.update(temperature, humidity, pressure);
    });
  }

  public void setMeasurements(float temperature, float humidity, float pressure) {
    this.temperature = temperature;
    this.humidity = humidity;
    this.pressure = pressure;
    measurementsChanged();
  }

  public void measurementsChanged() {
    notifyObservers();
  }
}

WeatherStation.java

package com.art.headfirst.WeatherStationApp.example;

public class WeatherStation {
    public static void main(String[] args) {

        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
        weatherData.setMeasurements(57.4f, 53, 29.95f);

    }
}

Summary

Observer pattern defines one-to-many relationship between a set of objects. It provides an object design where subjects and observers are loosely coupled.