Observer Pattern
Let any number of objects react when one object changes, without that object knowing who they are.
Overview
The Observer pattern is one of the behavioral patterns in Design Patterns (Gamma, Helm, Johnson and Vlissides, 1994). One object, the subject, holds some state that others care about. Instead of the subject calling each of them by name, the interested objects, the observers, register with the subject, and the subject tells all of them whenever its state changes. The subject knows only that each observer has an update method. It does not know what they do with the news.
Every event system is this pattern: a button that runs handlers when clicked, a data model that repaints views, a price feed that triggers alerts. Interviewers ask about Observer to see whether you can decouple a change from its effects, and whether you know the three classic failures: observers that are never removed and leak memory, observers that change the subject and cause loops, and notifications whose order or timing surprises people.
The problem it solves
A thermostat reads a temperature. A display shows it, an alarm checks it, a log records it. If the thermostat calls all three directly, it must import all three, and adding a fourth means editing the thermostat. Worse, the thermostat cannot be reused anywhere the display does not exist.
- The subject imports and calls every dependent — The subject holds a list of observers and calls update on each
- Adding a dependent means editing the subject — Adding a dependent means calling attach
- Dependents exist for the subject's whole lifetime — Dependents come and go at run time
- Easy to read, tightly coupled — Loosely coupled, harder to trace
Structure
- Subject — Keeps the observer list; offers attach, detach and notify — Thermostat
- Observer interface — One method the subject can call — update(value)
- Concrete observers — Do something with the change — Display, HeatAlarm
- Client — Wires observers to subjects — the setup code
Push or pull
The subject can send the changed data in the call (push), or send only a signal and let each observer ask for what it needs (pull). The example above pushes the temperature. A pull design would call update(thermostat) and let the display read thermostat.temperature itself.
- The call — update(value) — update(subject)
- Observer needs to know the subject's interface — No — Yes
- Data sent that some observers ignore — Yes — No
- Observer can read several fields at once — Only what was pushed — Anything public
- Good for — Small, single-valued events — Rich subjects with many fields
Where you already use it
- Node.js EventEmitter — an emitter — a listener function — Listeners run synchronously; more than 10 listeners on one event prints a memory-leak warning by default
- Browser DOM — an EventTarget — a handler passed to addEventListener — once: true removes the handler after one call; an AbortSignal removes it on abort
- Java java.util.Observer — Observable — Observer — Deprecated since Java 9; the docs point to java.beans, java.util.concurrent and the Flow API instead
The Java deprecation note is worth reading because it lists the pattern's weak points in one place: a thin event model, an unspecified notification order, and no one-to-one link between state changes and notifications.
What you will be able to do
- Draw the subject, the observer interface and two concrete observers, and explain what each knows about the others.
- Implement attach, detach and notify, and say why notify iterates over a copy.
- Choose push or pull for a given subject and defend the choice.
- Name the lapsed listener leak and fix it with an explicit detach, a weak reference or an abort signal.
- Explain how Observer differs from publish-subscribe and how reactive libraries build on it.
Interview questions
- What is the lapsed listener problem, and how do you prevent it?
- What goes wrong when an observer modifies the subject during a notification, and how do you guard against it?
- How is Observer different from publish-subscribe?
- Should a subject notify observers synchronously or asynchronously?
- How does reactive programming extend the Observer pattern?
Sign up free to read the full topic
More Low-Level Design topics
Start free on Cariara · Coding problems · System design studio