Observer Design Pattern in Java

1. Definition

The Observer Design Pattern defines a one-to-many dependency between objects so that when one object (subject) changes state, all its dependent objects (observers) are notified and updated automatically.

2. Problem Statement

How can an object notify other objects about changes to its state without being tightly coupled to those other objects?

3. Solution

The Observer pattern provides a solution by letting subjects and observers remain loosely coupled. The subject only knows about its observers by an abstract interface. When a change occurs, the subject broadcasts to all registered observers.

4. Real-World Use Cases

1. A weather station providing updates to multiple display elements.

2. A stock system notifying investors when a stock reaches a certain price.

3. News portals updating subscribers with latest news.

5. Implementation Steps

1. Define Observer and Subject interfaces.

2. Concrete subjects maintain a list of observers and implement methods to add, remove, and notify them.

3. Concrete observers register with the subject and get updates.

6. Implementation

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

// Subject Interface
interface Subject {
    void register(Observer observer);
    void unregister(Observer observer);
    void notifyObservers();
}

// Concrete Subject
class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String state;

    public void setState(String state) {
        this.state = state;
        notifyObservers();
    }

    public void register(Observer observer) {
        observers.add(observer);
    }

    public void unregister(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(state);
        }
    }
}

// Concrete Observer
class ConcreteObserver implements Observer {
    private String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println("Observer " + name + " received message: " + message);
    }
}

// Client
public class ObserverPatternDemo {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();

        Observer observer1 = new ConcreteObserver("Observer 1");
        Observer observer2 = new ConcreteObserver("Observer 2");

        subject.register(observer1);
        subject.register(observer2);

        subject.setState("New State 1");
        subject.setState("New State 2");
    }
}

Output:

Observer Observer 1 received message: New State 1
Observer Observer 2 received message: New State 1
Observer Observer 1 received message: New State 2
Observer Observer 2 received message: New State 2

Explanation

The ConcreteSubject maintains a list of observers. When its state changes (via setState), it notifies all registered observers. The ConcreteObserver is an implementation of the Observer that gets updates from the Subject.

7. When to use?

Use the Observer Pattern when:

1. A change to one object requires changing others, and you don’t know how many objects need to be changed.

2. An object needs to notify other objects without making assumptions about who these objects are.

3. You want to create a loosely coupled system where the subject and the observers can interact but remain independent.


Comments