Posts Design Pattern: Observer
Post
Cancel

Design Pattern: Observer

OBSERVER

The Observer design pattern is a behavioral design pattern that establishes a one-to-many dependency between objects, so that when one object changes its state, all the dependent objects are automatically notified and updated. This is similar to a pub/sub model. The Subject is the one which needs to be observed by multiple Observers. When something changes in the subject, it notifies all the observers which can take appropriate actions.

OVERVIEW (UML)

snapshot Created using PlantUML.

Let’s imagine a scenario where we have a weather station that collects weather data (such as temperature, humidity, and pressure) and wants to notify multiple displays when the weather conditions change. To implement the Observer design pattern, we’ll create three main components: the Subject, the Observers, and the Concrete Subject.

CODE WALKTHROUGH

SUBJECT INTERFACE - THE THING TO BE OBSERVED

This is the interface that defines the methods for registering, removing, and notifying observers.

1
2
3
4
5
6
7
8
9
10
package com.designpattern;

public interface Subject {

 void registerObserver(Observer observer);
 void removeObserver(Observer observer);
 void notifyObservers();
 
}

OBSERVER - THE ONES WHICH NEED TO BE NOTIFIED WHEN THE SUBJECT CHANGES

This is the interface that defines the method to be called when the subject notifies the observers.

1
2
3
4
5
6
7
8
package com.designpattern;

public interface Observer {

 void update(float temperature, float humidity, float pressure);
 
}

WEATHER STATION - SUBJECT IMPLEMENTATION

This is the class that implements the Subject interface and holds the current weather data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.designpattern;

import java.util.ArrayList;
import java.util.List;

public class WeatherStation implements Subject {

 List<Observer> observers;
 private float temperature;
 private float humidity;
 private float pressure;

 public WeatherStation() {
  observers = new ArrayList<Observer>();
 }

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

 @Override
 public void removeObserver(Observer observer) {
  observers.remove(observer);
 }

 @Override
 public void notifyObservers() {

  //Iterate over the list of observers and calls their update() method.
  for (Observer observer : observers) {
   observer.update(temperature, humidity, pressure);
  }

 }
 
 //update the measurements and call the notifyObserver() method
 public void setMeasurements(float temperature, float humidity, float pressure) {
  
  this.temperature = temperature;
  this.humidity = humidity;
  this.pressure = pressure;
  
  notifyObservers();
  
 }

}

DISPLAY - OBSERVER IMPLEMENTATION

This will mimic an observer which needs to be notified when the subject (WeatherStation) get an update, in this case, the method setMeasurement() is called.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.designpattern;

public class Display implements Observer{

 private String displayName;
 
 public Display(String displayName) {
  this.displayName = displayName;
 }
 
 @Override
 public void update(float temperature, float humidity, float pressure) {
  
  System.out.println("Notified: " + displayName);
  
        System.out.println("Temperature: " + temperature);
        System.out.println("Humidity: " + humidity);
        System.out.println("Pressure: " + pressure);
        System.out.println();
  
 }

}

CLIENT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.demo;

import com.designpattern.Display;
import com.designpattern.WeatherStation;

public class App {

 public static void main(String[] args) {

  WeatherStation weatherStation = new WeatherStation();

  Display display1 = new Display("display1");
  Display display2 = new Display("display2");

  weatherStation.registerObserver(display1);
  weatherStation.registerObserver(display2);

  weatherStation.setMeasurements(25.5f, 65.2f, 1013.2f);
  
  weatherStation.removeObserver(display1);
  weatherStation.setMeasurements(25.0f, 75.2f, 1017.2f);

 }

}

OUTPUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Notified: display1
Temperature: 25.5
Humidity: 65.2
Pressure: 1013.2

Notified: display2
Temperature: 25.5
Humidity: 65.2
Pressure: 1013.2

Notified: display2
Temperature: 25.0
Humidity: 75.2
Pressure: 1017.2
This post is licensed under CC BY 4.0 by the author.