Observer Pattern

Difficulty: Intermediate

Question

Explain the Observer pattern. Implement a YouTube channel notifying subscribers and mention real-world uses.

Answer

The Observer pattern lets one object, the subject, notify many other objects, the observers, whenever its state changes, without knowing who those observers are or what they do. Think of subscribing to a YouTube channel. The channel does not know each viewer personally. It simply keeps a list of subscribers, and when a video is uploaded it goes through the list and pings everyone. Viewers can subscribe or unsubscribe at any time without the channel's code changing.

The problem it solves is tight coupling in one-to-many dependencies. Without it, the channel would need direct calls like emailService.send(), mobileApp.push(), and analytics.record() hard-coded in the upload method, so adding a new consumer means editing the channel. With Observer, the subject depends only on a small Observer interface with an update method. Any class implementing it can register. This is a beautiful example of the Open/Closed Principle and Dependency Inversion together.

The structure has four pieces. The Subject interface or class has attach, detach, and notify operations and keeps a list of observers. The Observer interface declares the update method. Concrete subjects hold the state of interest. Concrete observers implement update to react to changes. In the push model, the subject sends the changed data along in update; in the pull model, it merely says something changed and the observer queries the subject for details.

Where do you see it in the real world? Every event-listener system in GUIs: a button click notifies listeners, and in JavaScript addEventListener is exactly this. Publish-subscribe messaging systems like Kafka, RabbitMQ and Redis channels are distributed cousins. Model-View-Controller uses it so views update automatically when the model changes. Reactive libraries such as RxJava and Flow, Android LiveData, spreadsheet cell recalculation, stock price tickers, and email newsletters all follow the idea. Java has java.util.Observable and Observer, but they have been deprecated since Java 9 because they are not type-safe and not thread-safe, and PropertyChangeListener or your own interface is preferred.

Pitfalls to mention. Memory leaks happen when observers forget to unsubscribe, since the subject keeps a strong reference, which is known as the lapsed listener problem. Notification order is usually unspecified, so observers must not depend on it. If an observer throws an exception, it can stop the others from being notified unless you guard the loop. If observers modify the subject in their update method, you can get infinite loops or ConcurrentModificationException while iterating. And with multiple threads you need a thread-safe list such as CopyOnWriteArrayList.

Compare with the related Pub-Sub pattern: in Observer, observers register directly with the subject, so they know each other's existence in the sense of a reference. In Pub-Sub, a message broker sits in between, and publishers and subscribers are completely decoupled.

Code examples

YouTube channel and subscribers

import java.util.*;

interface Subscriber { void update(String video); }

class Channel {
    private final List<Subscriber> subscribers = new ArrayList<>();

    void subscribe(Subscriber s)   { subscribers.add(s); }
    void unsubscribe(Subscriber s) { subscribers.remove(s); }

    void upload(String video) {
        for (Subscriber s : subscribers) s.update(video);
    }
}

public class ObserverDemo {
    public static void main(String[] args) {
        Channel channel = new Channel();
        Subscriber asha = v -> System.out.println("Asha got: " + v);
        Subscriber ravi = v -> System.out.println("Ravi got: " + v);

        channel.subscribe(asha);
        channel.subscribe(ravi);
        channel.upload("OOP in 10 minutes");

        channel.unsubscribe(ravi);
        channel.upload("SOLID explained");
    }
}

Key points

Concepts covered

observer, design-patterns, behavioral, pub-sub, event-driven