Behavioral PatternBEGINNER8 min deep dive

Observer Pattern (Pub/Sub) Pattern

Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified automatically.

Real-World Mental Model / Metaphor:

A newspaper subscription or YouTube channel. When the YouTuber uploads a new video, all subscribed viewers receive an instant notification on their phones.

Interactive Runtime Simulator

Test and tweak inputs dynamically

Interactive Observer Pattern (Pub/Sub) SimulatorLIVE PLAYGROUND

Interact with the controls below to see how this design pattern executes in memory at runtime.

Category: Behavioral
1. Configure Observers (Subscribers):
Select Event to Emit:
EVENT BUS DISPATCH LOGS3 Active Observers
Click “Publish Event” to watch the subject notify all active subscribers.
The Problem It Solves

Polling. Observers periodically asking the subject 'Has your state changed yet?' wastes CPU and bandwidth.

The Architectural Solution

The Subject maintains a list of Observers and provides `subscribe()` and `unsubscribe()` methods. When state changes, the Subject loops through and calls `observer.update(event)`.

Pattern Structure & Participants

ParticipantRole & ResponsibilityType
Subject (Publisher)Maintains subscriber list and broadcasts eventsclass
Observer (Subscriber)Interface with update() methodinterface
EmailNotifier, SlackBotConcrete subscribers reacting to updatesclass
Collaboration Rules:
  • Subscribers register with subject.subscribe(observer)
  • When event occurs, subject calls observer.update(data)

Production Code Implementation

Observer Pattern (Pub/Sub).java
// 1. Observer Interface
public interface OrderObserver {
    void onOrderEvent(String orderId, String eventType);
    String getChannelName();
}

// 2. Concrete Observers
public class EmailNotificationService implements OrderObserver {
    public void onOrderEvent(String orderId, String event) {
        System.out.println("[EMAIL] Dispatching email confirmation for order: " + orderId);
    }
    public String getChannelName() { return "Email"; }
}

public class SlackAlertService implements OrderObserver {
    public void onOrderEvent(String orderId, String event) {
        System.out.println("[SLACK #sales] New order event: " + event + " (ID: " + orderId + ")");
    }
    public String getChannelName() { return "Slack"; }
}

// 3. Subject (Publisher)
public class OrderManager {
    private final List<OrderObserver> listeners = new CopyOnWriteArrayList<>();

    public void subscribe(OrderObserver observer) {
        listeners.add(observer);
    }

    public void unsubscribe(OrderObserver observer) {
        listeners.remove(observer);
    }

    public void notify(String orderId, String eventType) {
        for (OrderObserver listener : listeners) {
            listener.onOrderEvent(orderId, eventType);
        }
    }
}
When to Use:
  • •When changes to the state of one object may require changing other objects, and the set of objects is not known beforehand.
  • •When some objects in your app must observe others, but only for a limited time or in specific cases.
When to Avoid (Anti-Pattern):
  • •When the notification chain can trigger circular dependency loops.
  • •When order of notifications matters critically (publishers do not guarantee subscriber order).

Staff Engineering Interview Insights & Gotchas

  • Mention the 'Lapsed Listener' memory leak: how garbage collection cannot reclaim observers if the subject holds a strong reference to them.
  • Explain how Observer is the architectural foundation of Reactive Programming (Rx, WebSockets, Kafka).