Observer Design Pattern: Weather Monitoring System
Design Pattern

Observer Design Pattern: Weather Monitoring System

S

Shivam Chauhan

3 months ago

The Observer Design Pattern is a behavioral design pattern that defines a one-to-many relationship between objects. When one object (Subject) changes state, all its dependents (Observers) are notified and updated automatically. It is commonly used in event-driven systems, notifications, and real-time applications.

In this guide, we'll break down:

  • What the Observer Design Pattern is.
  • When to use it.
  • How to implement it in Java with a practical example.
  • Key benefits and trade-offs of the pattern.

What is the Observer Design Pattern?

The Observer Pattern defines a relationship where one object (the Subject) notifies multiple other objects (the Observers) about changes in its state. Observers register with the subject and are updated whenever the subject’s state changes.

It’s like a publish-subscribe model:

  • Subject: Maintains a list of observers and notifies them of changes.
  • Observers: Act upon receiving updates from the subject.

When to Use the Observer Pattern

The Observer Pattern is ideal for:

  1. Event-driven Systems: When multiple components need to respond to events, like UI updates.
  2. Notifications: Implementing a system to notify subscribers of changes, such as stock prices or weather updates.
  3. Decoupling: Keeping the Subject and Observers loosely coupled so they can evolve independently.

Real-World Example: Weather Monitoring System

Let’s implement a weather monitoring system where multiple devices (observers) display the temperature whenever it changes.

Observer Pattern in Java

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

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

// Observer Interface
interface Observer {
    void update(float temperature);
}

// Concrete Subject
class WeatherStation implements Subject {
    private List<Observer> observers;
    private float temperature;

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

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

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

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

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }
}

// Concrete Observer 1: Phone Display
class PhoneDisplay implements Observer {
    private float temperature;

    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        System.out.println("Phone Display: Temperature updated to " + temperature + "°C");
    }
}

// Concrete Observer 2: TV Display
class TVDisplay implements Observer {
    private float temperature;

    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        System.out.println("TV Display: Temperature updated to " + temperature + "°C");
    }
}

// Client Code
public class Client {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();

        // Create observers
        Observer phoneDisplay = new PhoneDisplay();
        Observer tvDisplay = new TVDisplay();

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

        // Simulate temperature change
        weatherStation.setTemperature(25.5f);
        weatherStation.setTemperature(30.0f);
    }
}

Explanation of Code:

  1. Subject Interface: Defines methods to register, remove, and notify observers.
  2. Observer Interface: Declares the update() method to be implemented by observers.
  3. Concrete Subject: WeatherStation manages a list of observers and notifies them of state changes.
  4. Concrete Observers: PhoneDisplay and TVDisplay respond to temperature updates.

Output:

plaintext
Phone Display: Temperature updated to 25.5°C  
TV Display: Temperature updated to 25.5°C  
Phone Display: Temperature updated to 30.0°C  
TV Display: Temperature updated to 30.0°C  

UML Diagram for Observer Pattern

Here’s the UML diagram for our Weather Monitoring System:

Drag: Pan canvas

Benefits of the Observer Pattern

  • Loose Coupling: The subject and observers are decoupled, improving maintainability.
  • Dynamic Updates: Observers are automatically updated when the subject changes.
  • Flexibility: Add or remove observers without modifying the subject.

Drawbacks of the Observer Pattern

  • Memory Leaks: Observers that are not unregistered can cause memory issues.
  • Performance Overhead: Notifying a large number of observers can impact performance.

Conclusion

The Observer Design Pattern is ideal for systems where multiple objects need to stay synchronized with a subject’s state. By following the principles of loose coupling and dynamic updates, this pattern makes your code modular, maintainable, and scalable.

Start implementing the Observer Pattern in your projects to handle real-time updates like a pro!

About the Author

S

Shivam Chauhan

Sharing insights about system design and coding practices.