Observer Pattern
The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. Use it when multiple parts of your system need to react to changes in a single source of truth.
Overview
The Observer pattern establishes a subscription mechanism that lets multiple objects listen for events emitted by another object. The subject maintains a list of observers and notifies them whenever its state changes, without knowing or caring what those observers do with the information. This decouples the source of change from the consumers of change, making it straightforward to add new reactions without modifying the emitter.
When to use it
- A change in one object should trigger updates in others, and you don't want tight coupling between them.
- The number of dependents is unknown at compile time or changes at runtime (dynamic subscriptions).
- You're building an event-driven architecture — UI event handlers, message brokers, reactive streams.
Example
interface Observer<T> {
update(data: T): void;
}
class Subject<T> {
private observers: Observer<T>[] = [];
subscribe(observer: Observer<T>) {
this.observers.push(observer);
}
unsubscribe(observer: Observer<T>) {
this.observers = this.observers.filter(o => o !== observer);
}
notify(data: T) {
this.observers.forEach(o => o.update(data));
}
}
const priceTracker = new Subject<number>();
priceTracker.subscribe({
update(price) { console.log(`Dashboard: $${price}`); }
});
priceTracker.subscribe({
update(price) {
if (price < 100) console.log('Alert: price dropped!');
}
});
priceTracker.notify(95);Pros
- Loose coupling — the subject knows nothing about its observers beyond the interface.
- New observers can be added at any time without modifying existing code.
- Follows the open/closed principle: open for extension, closed for modification.
Cons
- Notification order is not guaranteed, which can cause subtle bugs if observers depend on each other.
- Memory leaks can occur if observers are not properly unsubscribed.
- Debugging cascading updates can be difficult when many observers react to the same event.