Observer Pattern
The Observer pattern defines one-to-many dependency: when subject state changes, observers update automatically.
Introduction
The Observer pattern defines one-to-many dependency: when subject state changes, observers update automatically. Movie seat availability, stock prices, and order status notifications fit naturally.
Java's deprecated Observable/Observer is avoid — implement custom interfaces or use event bus in production. In interviews, clear Subject/Observer interfaces show you understand decoupled notification.
Watch for memory leaks if observers are not unregistered.
Understanding the topic
Key concepts
- Subject maintains observer list and notifies on change.
- Observer interface with update/onEvent method.
- Push model sends data; pull model lets observer query.
- Decouples event source from UI, email, SMS handlers.
- Domain events variant in DDD-style designs.
- Thread safety if notifications cross threads.
flowchart LRSubject -->|notify| ObserverASubject -->|notify| ObserverB
Step-by-step explanation
- Subject exposes subscribe/unsubscribe.
- Observers register interest.
- State change calls notifyObservers().
- Each observer handles event idempotently.
- Unsubscribe when observer lifecycle ends.
- Optional event object carries payload.
Informative example
Seat availability subject notifying booking UI observers:
public interface SeatObserver {void onSeatsChanged(String showId, Set<String> available);}public final class SeatInventory implements SeatObserver {private final Set<SeatObserver> observers = new CopyOnWriteArraySet<>();private final Map<String, Set<String>> availableByShow = new ConcurrentHashMap<>();public void subscribe(SeatObserver observer) { observers.add(observer); }public void release(String showId, String seatId) {availableByShow.computeIfAbsent(showId, k -> ConcurrentHashMap.newKeySet()).add(seatId);notify(showId);}private void notify(String showId) {Set<String> seats = Set.copyOf(availableByShow.getOrDefault(showId, Set.of()));observers.forEach(o -> o.onSeatsChanged(showId, seats));}@Overridepublic void onSeatsChanged(String showId, Set<String> available) { /* no-op for self */ }}
CopyOnWriteArraySet safe for iterate-notify; production may use event bus — pattern intent matters in interviews.
Real-world use
Real-world applications
- UI updates on model changes.
- Order status notifications.
- Metrics listeners on cache eviction.
Best practices
- Keep observer callbacks fast — offload heavy work.
- Use weak references or explicit unsubscribe.
- Immutable event payloads prevent races.
- Consider ordered delivery requirements.
- Idempotent handlers for duplicate events.
Common mistakes
- Observer doing transactional side effects synchronously.
- Circular notify loops between subjects.
- Forgotten unsubscribe leaking memory.
- Fat observer interface forcing empty methods (ISP violation).
Advanced interview questions
Q1BeginnerWhat is Observer pattern?
Q2BeginnerObserver vs pub/sub?
Q3IntermediateHow prevent memory leaks?
Q4IntermediateThread-safe observer list?
Q5AdvancedDesign notify for splitwise expense added.
Summary
Observer decouples state change from reactions. Subject maintains subscriber list. Unregister observers to avoid leaks. Keep notification handlers lightweight. Foundation for event-driven LLD modules.