Observer
Define a one-to-many dependency so dependents are notified automatically when state changes.
One object changes, and several others need to know. An order is placed, so you send an email, update stock and refresh a dashboard.
The simple approach is for the order code to call all three. But now it depends on all three. Adding a fourth means editing it again, and testing it means having all of them available.
Observer flips this around. Interested objects register themselves. The source keeps a list and notifies everyone on it, without knowing what any of them actually do.
What the interviewer is probing.
1. "What does Observer decouple?" *Probing:* the purpose. *Stalls:* "Objects." *Moves up:* the subject from its dependents — it notifies without knowing who is listening or what they do.
2. "What are the hazards in a naive implementation?" *Probing:* the practical failure. *Stalls:* "None." *Moves up:* memory leaks from observers never unregistered, unpredictable notification order, and an exception in one observer breaking the rest.
3. "How does it relate to pub/sub?" *Probing:* the distinction. *Stalls:* "The same." *Moves up:* Observer is usually in-process with direct references; pub/sub adds a broker so the two sides never know each other at all.
4. "What is the modern form?" *Probing:* currency. *Stalls:* "The Observer interface." *Moves up:* reactive streams and event buses — Java's own Observer and Observable were deprecated for being too weak.
A YouTube channel — upload a video and all subscribers get notified. Subscribers can join or leave freely.
Key Concepts
public class EventManager {
private final Map<String, List<EventListener>> listeners = new HashMap<>();
public void subscribe(String event, EventListener l) {
listeners.computeIfAbsent(event, k -> new ArrayList<>()).add(l);
}
public void unsubscribe(String event, EventListener l) {
listeners.getOrDefault(event, List.of()).remove(l);
}
public void notify(String event, Object data) {
for (EventListener l : listeners.getOrDefault(event, List.of())) {
l.update(event, data);
}
}
}