Observer is a behavioural design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.

When one object (the Publisher) changes its state, all its dependents (Subscribers) are automatically notified and updated.


Scenario: Weather Updates Subscription

Imagine you have a weather updates service. People who are interested in weather updates can subscribe to this service. Whenever the weather changes, the service notifies all its subscribers automatically.

Subscriber/Listener (Observers): These are the individuals who want to receive weather updates.

Publisher (Subject): This is the weather updates service that maintains a list of subscribers and notifies them when the weather changes.

<img src=“https://refactoring.guru/images/patterns/diagrams/observer/solution1-en-2x.png” width=“500” height=“600”>


Below, is the Java code for the Observer design pattern.

WeatherStationService.java:(Publisher)

import java.util.ArrayList;
import java.util.List;
 
class WeatherStation {
    private List<DisplayScreen> subscribers = new ArrayList<>();
    private float temperature;
 
    public void addSubscriber(DisplayScreen observer) {
        observers.add(observer);
    }
 
    public void removeSubscriber(DisplayScreen observer) {
        observers.remove(observer);
    }
 
    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }
 
    private void notifySubscriber() {
        for (DisplayScreen subscriber : subscribers) {
            observer.update(temperature);
        }
    }
}

<img src=“https://refactoring.guru/images/patterns/diagrams/observer/solution2-en-2x.png” width=“300” height=“600” >

DisplayScreen.java:

interface DisplayScreen {
    void update(float temperature);
}

PhoneDisplay.java: (Subscriber/Listener)

class PhoneDisplay implements DisplayScreen {
    public void update(float temperature) {
        System.out.println("Phone Display: Temperature is " + temperature + "°C");
    }
}

TVDisplay.java: (Subscriber/Listener)

class TVDisplay implements DisplayScreen {
    public void update(float temperature) {
        System.out.println("TV Display: Temperature is " + temperature + "°C");
    }
}

Main.java:

public class Main {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
 
        DisplayScreen phoneDisplay = new PhoneDisplay();
        DisplayScreen tvDisplay = new TVDisplay();
 
        weatherStation.addSubscriber(phoneDisplay);
        weatherStation.addSubscriber(tvDisplay);
 
        weatherStation.setTemperature(25.5f); // Notifies both displays
    }
}

Explanation: In this example, the WeatherStation is the subject that maintains a list of observers (DisplayScreen). When the temperature changes, the WeatherStation updates its state and notifies all registered observers. Each observer, such as PhoneDisplay and TVDisplay, implements the DisplayScreen interface and defines its update method, which is called by the weather station when there’s a change in temperature. This way, the display screens stay updated with the latest weather information without directly depending on each other.