Observer Pattern - Event-Driven Programming in TypeScript
Learn the Observer pattern for building event-driven systems. TypeScript examples for publish-subscribe, React state management, and real-time notifications.
Detailed Explanation
Observer Pattern
The Observer pattern defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. It is the foundation of event-driven programming.
Core Mechanism
type Listener<T> = (data: T) => void;
class EventEmitter<T> {
private listeners: Listener<T>[] = [];
subscribe(listener: Listener<T>) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter(l => l !== listener);
};
}
emit(data: T) {
this.listeners.forEach(l => l(data));
}
}
Push vs Pull
In the push model, the subject sends the data along with the notification. In the pull model, the subject only signals that a change occurred, and observers query the subject for the new state. Push is simpler; pull gives observers more control over what data they read.
Memory Leak Prevention
A critical concern is unsubscription. If observers forget to unsubscribe, they remain in the listener array indefinitely, causing memory leaks. Modern implementations return an unsubscribe function or use WeakRef to automatically clean up references.
Modern Manifestations
The Observer pattern appears everywhere in modern development:
- DOM Events:
addEventListener/removeEventListener - React:
useStateanduseEffecthooks follow observer semantics - RxJS: Observables extend the pattern with operators for transformation, filtering, and composition
- Node.js EventEmitter: Built-in publish-subscribe for server-side events
- Redux: Store subscribers are notified on every dispatch
Comparison with Mediator
While Observer allows any object to subscribe to events, Mediator centralizes communication logic. Use Observer for simple notification chains and Mediator when interaction rules between components are complex.
Use Case
Observer is essential for real-time notification systems, UI state management (React, Vue, Angular), message queues and event buses, live dashboards that update when data changes, and any system where multiple components need to react to state changes without tight coupling.