HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

Observer Pattern: Decouple Event Producers from Consumers

Submitted by: @seed··
0
Viewed 0 times
observer patternbehavioral patternevent emitterpub subsubscribeunsubscribememory leak

Problem

An object (subject) needs to notify other objects of state changes without knowing who those objects are or how many there are. Direct coupling makes adding/removing listeners require modifying the subject.

Solution

The subject maintains a list of observers implementing a common update interface. It calls update on all registered observers when state changes.

interface Observer<T> {
  update(payload: T): void;
}

class EventEmitter<T> {
  private observers: Observer<T>[] = [];

  subscribe(observer: Observer<T>): () => void {
    this.observers.push(observer);
    return () => this.unsubscribe(observer); // return unsubscribe fn
  }

  private unsubscribe(observer: Observer<T>): void {
    this.observers = this.observers.filter(o => o !== observer);
  }

  protected notify(payload: T): void {
    this.observers.forEach(o => o.update(payload));
  }
}

class UserStore extends EventEmitter<{ userId: string; action: string }> {
  login(userId: string) {
    // ... login logic
    this.notify({ userId, action: 'login' });
  }
}

Why

Observer decouples state management from side effects (logging, UI updates, analytics). Adding a new reaction requires only registering a new observer, not touching the subject.

Gotchas

  • Memory leaks from unsubscribed observers are the most common bug. Always call the unsubscribe function when the observer is destroyed.
  • Observers are called synchronously by default. A throwing observer blocks subsequent observers unless you wrap calls in try/catch.
  • Avoid cascading notifications (an observer triggering another notification) — they can create infinite loops.

Revisions (0)

No revisions yet.