Observer Design Pattern

Last Updated : 13 Feb, 2026

Observer Design Pattern is a behavioral pattern that creates a one-to-many relationship between a subject and its observers. When the subject's state changes, all dependent observers are notified and updated automatically, ensuring synchronized communication.

  • Enables automatic updates to multiple objects when one object changes.
  • Promotes loose coupling between the subject and its observers.
  • Useful for implementing event-driven or publish-subscribe systems.
observer-design-Pattern
Observer Design Pattern

Note: Subjects are the objects that maintain and notify observers about changes in their state, while Observers are the entities that react to those changes.

Components

Below are the main components of Observer Design Pattern:

class_diagram_of_observer_design_pattern
Class Diagram
  • Subject: Maintains a list of observers, provides methods to add/remove them, and notifies them of state changes.
  • Observer: Defines an interface with an update() method to ensure all observers receive updates consistently.
  • ConcreteSubject: A specific subject that holds actual data. On state change, it notifies registered observers (e.g., a weather station).
  • ConcreteObserver: Implements the observer interface and reacts to subject updates (e.g., a weather app showing weather updates).

Working

The Observer Pattern works by establishing a subscription mechanism between a subject and its observers so that changes in one object are automatically reflected in others.

  • Observers subscribe to the subject to receive updates.
  • The subject maintains a list of registered observers.
  • When the subject’s state changes, it notifies all observers.
  • Observers react to the update according to their own behavior.

Uses

The Observer Pattern is used when multiple objects need to be notified automatically about changes in another object’s state.

  • To implement event handling systems such as GUI listeners.
  • To maintain consistency between related objects without tight coupling.
  • To support publish–subscribe mechanisms.

Example: Weather Monitoring System

A WeatherStation acts as the Subject, and display devices such as PhoneDisplay and TVDisplay act as Observers. The observers register themselves with the weather station to receive updates.

When the weather changes using the setWeather() method, the WeatherStation automatically calls notifyObservers(), which triggers the update() method of all registered observers. As a result, both PhoneDisplay and TVDisplay receive and display the updated weather information without directly depending on the WeatherStation’s internal logic.

Implementation of above Example

This example shows the practical application of the design pattern using code.

1. Subject

  • The "Subject" interface outlines the operations a subject (like "WeatherStation") should support.
  • "addObserver" and "removeObserver" are for managing the list of observers.
  • "notifyObservers" is for informing observers about changes.
C++
public interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
Java
public interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
Python
from abc import ABC, abstractmethod

class Subject(ABC):
    @abstractmethod
    def add_observer(self, observer):
        pass

    @abstractmethod
    def remove_observer(self, observer):
        pass

    @abstractmethod
    def notify_observers(self):
        pass
JavaScript
class Subject {
    addObserver(observer) {
        // Implementation
    }

    removeObserver(observer) {
        // Implementation
    }

    notifyObservers() {
        // Implementation
    }
}

2. Observer

  • The "Observer" interface defines a contract for objects that want to be notified about changes in the subject ("WeatherStation" in this case).
  • It includes a method "update"that concrete observers must implement to receive and handle updates.
C++
public interface Observer {
    void update(String weather);
}
Java
public interface Observer {
    void update(String weather);
}
Python
from abc import ABC, abstractmethod

class Observer(ABC):
    @abstractmethod
    def update(self, weather: str):
        pass
JavaScript
class Observer {
    update(weather) {
        // Implementation here
    }
}

3. ConcreteSubject(WeatherStation)

  • "WeatherStation" is the concrete subject implementing the "Subject" interface.
  • It maintains a list of observers ("observers") and provides methods to manage this list.
  • "notifyObservers" iterates through the observers and calls their "update" method, passing the current weather.
  • "setWeather" method updates the weather and notifies observers of the change.
C++
#include <vector>
#include <string>
#include <algorithm>

class Observer {
public:
    virtual void update(const std::string& weather) = 0;
};

class Subject {
public:
    virtual void addObserver(Observer* observer) = 0;
    virtual void removeObserver(Observer* observer) = 0;
    virtual void notifyObservers() = 0;
};

class WeatherStation : public Subject {
private:
    std::vector<Observer*> observers;
    std::string weather;

public:
    void addObserver(Observer* observer) override {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) override {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notifyObservers() override {
        for (Observer* observer : observers) {
            observer->update(weather);
        }
    }

    void setWeather(const std::string& newWeather) {
        this->weather = newWeather;
        notifyObservers();
    }
};
Java
import java.util.ArrayList;
import java.util.List;

// Observer interface
interface Observer {
    void update(String weather);
}

// Subject interface
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// Concrete Subject
class WeatherStation implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String weather = "";

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

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

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(weather);
        }
    }

    public void setWeather(String newWeather) {
        this.weather = newWeather;
        notifyObservers();
    }
}
Python
from abc import ABC, abstractmethod
from typing import List

class Observer(ABC):
    @abstractmethod
    def update(self, weather: str):
        pass

class Subject(ABC):
    @abstractmethod
    def add_observer(self, observer: Observer):
        pass

    @abstractmethod
    def remove_observer(self, observer: Observer):
        pass

    @abstractmethod
    def notify_observers(self):
        pass

class WeatherStation(Subject):
    def __init__(self):
        self.observers: List[Observer] = []
        self.weather = ""

    def add_observer(self, observer: Observer):
        self.observers.append(observer)

    def remove_observer(self, observer: Observer):
        if observer in self.observers:
            self.observers.remove(observer)

    def notify_observers(self):
        for observer in self.observers:
            observer.update(self.weather)

    def set_weather(self, new_weather: str):
        self.weather = new_weather
        self.notify_observers()
JavaScript
class Observer {
    update(weather) {
        throw new Error('Method update() must be implemented.');
    }
}

class Subject {
    addObserver(observer) {
        throw new Error('Method addObserver() must be implemented.');
    }
    removeObserver(observer) {
        throw new Error('Method removeObserver() must be implemented.');
    }
    notifyObservers() {
        throw new Error('Method notifyObservers() must be implemented.');
    }
}

class WeatherStation extends Subject {
    constructor() {
        super();
        this.observers = [];
        this.weather = "";
    }
    addObserver(observer) {
        this.observers.push(observer);
    }
    removeObserver(observer) {
        this.observers = this.observers.filter(obs => obs !== observer);
    }
    notifyObservers() {
        this.observers.forEach(observer => observer.update(this.weather));
    }
    setWeather(newWeather) {
        this.weather = newWeather;
        this.notifyObservers();
    }
}

4. ConcreteObserver(PhoneDisplay)

  • "PhoneDisplay" is a concrete observer implementing the "Observer" interface.
  • It has a private field weather to store the latest weather.
  • The "update" method sets the new weather and calls the "display" method.
  • "display" prints the updated weather to the console.
C++
public class PhoneDisplay implements Observer {
    private String weather;

    @Override
    public void update(String weather) {
        this.weather = weather;
        display();
    }

    private void display() {
        System.out.println("Phone Display: Weather updated - " + weather);
    }
}
Java
import java.util.Observer;
import java.util.Observable;

public class PhoneDisplay implements Observer {
    private String weather;

    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof String) {
            this.weather = (String) arg;
            display();
        }
    }

    private void display() {
        System.out.println("Phone Display: Weather updated - " + weather);
    }
}
Python
from abc import ABC, abstractmethod

class Observer(ABC):
    @abstractmethod
    def update(self, weather):
        pass

class PhoneDisplay(Observer):
    def __init__(self):
        self.weather = ""

    def update(self, weather):
        self.weather = weather
        self.display()

    def display(self):
        print(f'Phone Display: Weather updated - {self.weather}')
JavaScript
class Observer {
    update(weather) {
        throw new Error('Method not implemented.');
    }
}

class PhoneDisplay extends Observer {
    constructor() {
        super();
        this.weather = "";
    }

    update(weather) {
        this.weather = weather;
        this.display();
    }

    display() {
        console.log(`Phone Display: Weather updated - ${this.weather}`);
    }
}

5. ConcreteObserver(TVDisplay)

  • "TVDisplay" is another concrete observer similar to "PhoneDisplay".
  • It also implements the "Observer" interface, with a similar structure to "PhoneDisplay".
C++
class TVDisplay implements Observer {
    private String weather;
 
    @Override
    public void update(String weather) {
        this.weather = weather;
        display();
    }
 
    private void display() {
        System.out.println("TV Display: Weather updated - " + weather);
    }
}
Java
class TVDisplay implements Observer {
    private String weather;
    
    @Override
    public void update(String weather) {
        this.weather = weather;
        display();
    }
    
    private void display() {
        System.out.println("TV Display: Weather updated - " + weather);
    }
}
Python
class TVDisplay:
    def __init__(self):
        self.weather = ""
    
    def update(self, weather):
        self.weather = weather
        self.display()
    
    def display(self):
        print(f'TV Display: Weather updated - {self.weather}')
JavaScript
class TVDisplay {
    constructor() {
        this.weather = "";
    }
    
    update(weather) {
        this.weather = weather;
        this.display();
    }
    
    display() {
        console.log(`TV Display: Weather updated - ${this.weather}`);
    }
}

6. Usage

  • In "WeatherApp", a "WeatherStation" is created.
  • Two observers ("PhoneDisplay" and "TVDisplay") are registered with the weather station using "addObserver".
  • The "setWeather" method simulates a weather change to "Sunny," triggering the "update" method in both observers.
  • The output shows how both concrete observers display the updated weather information.
C++
public class WeatherApp {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        Observer phoneDisplay = new PhoneDisplay();
        Observer tvDisplay = new TVDisplay();

        weatherStation.addObserver(phoneDisplay);
        weatherStation.addObserver(tvDisplay);

        // Simulating weather change
        weatherStation.setWeather("Sunny");

        // Output:
        // Phone Display: Weather updated - Sunny
        // TV Display: Weather updated - Sunny
    }
}
Java
public class WeatherApp {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        Observer phoneDisplay = new PhoneDisplay();
        Observer tvDisplay = new TVDisplay();

        weatherStation.addObserver(phoneDisplay);
        weatherStation.addObserver(tvDisplay);

        // Simulating weather change
        weatherStation.setWeather("Sunny");

    }
}
Python
from abc import ABC, abstractmethod

class Observer(ABC):
    @abstractmethod
    def update(self, weather):
        pass

class PhoneDisplay(Observer):
    def update(self, weather):
        print(f'Phone Display: Weather updated - {weather}')

class TVDisplay(Observer):
    def update(self, weather):
        print(f'TV Display: Weather updated - {weather}')

class WeatherStation:
    def __init__(self):
        self.observers = []
        self.weather = ""

    def add_observer(self, observer):
        self.observers.append(observer)

    def set_weather(self, weather):
        self.weather = weather
        self.notify_observers()

    def notify_observers(self):
        for observer in self.observers:
            observer.update(self.weather)

# Main execution
weather_station = WeatherStation()

phone_display = PhoneDisplay()
tv_display = TVDisplay()

weather_station.add_observer(phone_display)
weather_station.add_observer(tv_display)

# Simulating weather change
weather_station.set_weather('Sunny')

# Output:
# Phone Display: Weather updated - Sunny
# TV Display: Weather updated - Sunny
JavaScript
class Observer {
    update(weather) {
        throw new Error('Method not implemented.');
    }
}

class PhoneDisplay extends Observer {
    update(weather) {
        console.log(`Phone Display: Weather updated - ${weather}`);
    }
}

class TVDisplay extends Observer {
    update(weather) {
        console.log(`TV Display: Weather updated - ${weather}`);
    }
}

class WeatherStation {
    constructor() {
        this.observers = [];
        this.weather = "";
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    setWeather(weather) {
        this.weather = weather;
        this.notifyObservers();
    }

    notifyObservers() {
        this.observers.forEach(observer => observer.update(this.weather));
    }
}

// Main execution
const weatherStation = new WeatherStation();

const phoneDisplay = new PhoneDisplay();
const tvDisplay = new TVDisplay();

weatherStation.addObserver(phoneDisplay);
weatherStation.addObserver(tvDisplay);

// Simulating weather change
weatherStation.setWeather('Sunny');

// Output:
// Phone Display: Weather updated - Sunny
// TV Display: Weather updated - Sunny

Complete code for the above example

Below is the complete code for the above example:

C++
#include <iostream>
#include <vector>
#include <algorithm> // for std::remove
#include <string>
using namespace std;

// Observer Interface
class Observer {
public:
    virtual void update(const string& weather) = 0;
    virtual ~Observer() {}
};

// Subject Interface
class Subject {
public:
    virtual void addObserver(Observer* observer) = 0;
    virtual void removeObserver(Observer* observer) = 0;
    virtual void notifyObservers() = 0;
    virtual ~Subject() {}
};

// ConcreteSubject Class
class WeatherStation : public Subject {
private:
    vector<Observer*> observers; // list of observers
    string weather;

public:
    void addObserver(Observer* observer) override {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) override {
        observers.erase(remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notifyObservers() override {
        for (Observer* observer : observers) {
            observer->update(weather);
        }
    }

    void setWeather(const string& newWeather) {
        weather = newWeather;
        notifyObservers();
    }
};

// ConcreteObserver Class: PhoneDisplay
class PhoneDisplay : public Observer {
private:
    string weather;

    void display() {
        cout << "Phone Display: Weather updated - " << weather << endl;
    }

public:
    void update(const string& weather) override {
        this->weather = weather;
        display();
    }
};

// ConcreteObserver Class: TVDisplay
class TVDisplay : public Observer {
private:
    string weather;

    void display() {
        cout << "TV Display: Weather updated - " << weather << endl;
    }

public:
    void update(const string& weather) override {
        this->weather = weather;
        display();
    }
};

// Usage / Demo
int main() {
    WeatherStation weatherStation;

    PhoneDisplay phoneDisplay;
    TVDisplay tvDisplay;

    // Register observers
    weatherStation.addObserver(&phoneDisplay);
    weatherStation.addObserver(&tvDisplay);

    // Simulating weather changes
    weatherStation.setWeather("Sunny");
    weatherStation.setWeather("Rainy");
    weatherStation.setWeather("Cloudy");

    // Remove one observer
    weatherStation.removeObserver(&tvDisplay);

    // Notify remaining observer
    weatherStation.setWeather("Windy");

    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;

// Observer Interface
interface Observer {
    void update(String weather);
}

// Subject Interface
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// ConcreteSubject Class
class WeatherStation implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String weather;

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

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

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(weather);
        }
    }

    public void setWeather(String newWeather) {
        this.weather = newWeather;
        notifyObservers();
    }
}

// ConcreteObserver Class
class PhoneDisplay implements Observer {
    private String weather;

    @Override
    public void update(String weather) {
        this.weather = weather;
        display();
    }

    private void display() {
        System.out.println("Phone Display: Weather updated - " + weather);
    }
}

// ConcreteObserver Class
class TVDisplay implements Observer {
    private String weather;

    @Override
    public void update(String weather) {
        this.weather = weather;
        display();
    }

    private void display() {
        System.out.println("TV Display: Weather updated - " + weather);
    }
}

// Usage Class
public class WeatherApp {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        Observer phoneDisplay = new PhoneDisplay();
        Observer tvDisplay = new TVDisplay();

        // Register observers
        weatherStation.addObserver(phoneDisplay);
        weatherStation.addObserver(tvDisplay);

        // Simulating weather changes
        weatherStation.setWeather("Sunny");
        weatherStation.setWeather("Rainy");
        weatherStation.setWeather("Cloudy");

        // Remove one observer
        weatherStation.removeObserver(tvDisplay);

        // Notify remaining observer
        weatherStation.setWeather("Windy");
    }
}
Python
from abc import ABC, abstractmethod
from typing import List

# Observer Interface
class Observer(ABC):
    @abstractmethod
    def update(self, weather: str):
        pass

# Subject Interface
class Subject(ABC):
    @abstractmethod
    def add_observer(self, observer: Observer):
        pass

    @abstractmethod
    def remove_observer(self, observer: Observer):
        pass

    @abstractmethod
    def notify_observers(self):
        pass

# ConcreteSubject Class
class WeatherStation(Subject):
    def __init__(self):
        self.observers: List[Observer] = []
        self.weather = ""

    def add_observer(self, observer: Observer):
        self.observers.append(observer)

    def remove_observer(self, observer: Observer):
        self.observers.remove(observer)

    def notify_observers(self):
        for observer in self.observers:
            observer.update(self.weather)

    def set_weather(self, new_weather: str):
        self.weather = new_weather
        self.notify_observers()

# ConcreteObserver Class
class PhoneDisplay(Observer):
    def __init__(self):
        self.weather = ""

    def update(self, weather: str):
        self.weather = weather
        self.display()

    def display(self):
        print(f'Phone Display: Weather updated - {self.weather}')

# ConcreteObserver Class
class TVDisplay(Observer):
    def __init__(self):
        self.weather = ""

    def update(self, weather: str):
        self.weather = weather
        self.display()

    def display(self):
        print(f'TV Display: Weather updated - {self.weather}')

# Usage
if __name__ == '__main__':
    weather_station = WeatherStation()

    phone_display = PhoneDisplay()
    tv_display = TVDisplay()

    weather_station.add_observer(phone_display)
    weather_station.add_observer(tv_display)

    # Simulating weather change
    weather_station.set_weather('Sunny')
    # Output:
    # Phone Display: Weather updated - Sunny
    # TV Display: Weather updated - Sunny
JavaScript
// Observer Interface
class Observer {
    update(weather) {
        throw new Error('Method not implemented.');
    }
}

// Subject Interface
class Subject {
    addObserver(observer) {
        throw new Error('Method not implemented.');
    }

    removeObserver(observer) {
        throw new Error('Method not implemented.');
    }

    notifyObservers() {
        throw new Error('Method not implemented.');
    }
}

// ConcreteSubject Class
class WeatherStation extends Subject {
    constructor() {
        super();
        this.observers = [];
        this.weather = "";
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        this.observers = this.observers.filter(obs => obs !== observer);
    }

    notifyObservers() {
        this.observers.forEach(observer => observer.update(this.weather));
    }

    setWeather(newWeather) {
        this.weather = newWeather;
        this.notifyObservers();
    }
}

// ConcreteObserver Class
class PhoneDisplay extends Observer {
    constructor() {
        super();
        this.weather = "";
    }

    update(weather) {
        this.weather = weather;
        this.display();
    }

    display() {
        console.log(`Phone Display: Weather updated - ${this.weather}`);
    }
}

// ConcreteObserver Class
class TVDisplay extends Observer {
    constructor() {
        super();
        this.weather = "";
    }

    update(weather) {
        this.weather = weather;
        this.display();
    }

    display() {
        console.log(`TV Display: Weather updated - ${this.weather}`);
    }
}

// Usage
const weatherStation = new WeatherStation();

const phoneDisplay = new PhoneDisplay();
const tvDisplay = new TVDisplay();

weatherStation.addObserver(phoneDisplay);
weatherStation.addObserver(tvDisplay);

// Simulating weather change
weatherStation.setWeather('Sunny');
// Output:
// Phone Display: Weather updated - Sunny
// TV Display: Weather updated - Sunny

Output
Phone Display: Weather updated - Sunny
TV Display: Weather updated - Sunny
Phone Display: Weather updated - Rainy
TV Display: Weather updated - Rainy
Phone Display: Weather updated - Cloudy
TV Display...

Real Life Example

The Observer pattern is widely used in applications where one object’s state changes need to be automatically reflected in multiple other objects:

  • Social Media Notifications
    Users (observers) get updates when someone they follow (subject) posts new content or status.
  • Stock Market Apps
    Investors receive real-time updates when stock prices (subjects) change.
  • Event Listeners in GUIs
    UI components observe user actions like clicks or keyboard input and respond accordingly.
  • Weather Monitoring Systems
    Multiple displays or devices update automatically when the central weather data changes.

Advantages

The Observer Pattern improves flexibility and communication between objects.

  • Provides loose coupling between subject and observers.
  • Allows easy addition or removal of observers at runtime.
  • Ensures automatic and consistent updates to all dependents.

Disadvantages

Despite its benefits, the Observer Pattern has some drawbacks.

  • Can lead to performance issues if there are many observers.
  • Debugging becomes harder due to indirect communication.
  • Observers may receive unnecessary updates if not managed carefully.
Comment

Explore