Back to All Design Patterns
Pattern 10 of 22
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 dynamicallyInteractive Observer Pattern (Pub/Sub) SimulatorLIVE PLAYGROUND
Interact with the controls below to see how this design pattern executes in memory at runtime.
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
| Participant | Role & Responsibility | Type |
|---|---|---|
| Subject (Publisher) | Maintains subscriber list and broadcasts events | class |
| Observer (Subscriber) | Interface with update() method | interface |
| EmailNotifier, SlackBot | Concrete subscribers reacting to updates | class |
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).