Observer Design Pattern (original) (raw)

Last Updated : 7 Jun, 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.

**Example: A YouTube channel (Subject) notifies all its subscribers (Observers) whenever a new video is uploaded.

observer-design-Pattern

Observer Design Pattern

In the Diagram

**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.

Real-Life Applications

The Observer pattern is widely used in applications where changes in one object need to be automatically reflected in multiple others:

Components

The main components of Observer Design Pattern are:

class_diagram_of_observer_design_pattern

Class Diagram

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.

Uses

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

Implementation Example

Problem statement

Imagine a weather monitoring system where multiple display devices like phone and TV need to show updated weather information. Whenever the weather changes, all devices should receive updates automatically without being tightly connected to the weather system.

The Observer pattern solves this by allowing devices (observers) to register with a WeatherStation (subject). When the weather changes using setWeather(), it notifies all observers, and they update their display accordingly.

**1. Subject

class Observer; // Forward declaration

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

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

#include

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

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)

#include #include #include

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 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)

class PhoneDisplay : public Observer { private: string weather;

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

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

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)

class TVDisplay : public Observer { private: string weather;

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

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

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

#include #include using namespace std;

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

class PhoneDisplay : public Observer { public: void update(string weather) override { cout << "Phone Display: " << weather << endl; } };

class TVDisplay : public Observer { public: void update(string weather) override { cout << "TV Display: " << weather << endl; } };

class WeatherStation { private: vector<Observer*> observers; string weather; public: void addObserver(Observer* observer) { observers.push_back(observer); } void setWeather(string newWeather) { weather = newWeather; notifyObservers(); } void notifyObservers() { for (Observer* observer : observers) { observer->update(weather); } } };

int main() { WeatherStation weatherStation;

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

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

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

delete phoneDisplay;
delete tvDisplay;
return 0;

}

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

The complete code for the above example is:

C++ `

#include #include #include // for std::remove #include 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 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...

Advantages

The Observer Pattern improves flexibility and communication between objects.

Disadvantages

Despite its benefits, the Observer Pattern has some drawbacks.