Skip to main content

Observer

Overview​

Define a one-to-many dependency so that when one object changes state, all dependents are notified.

When to use​

  • You need event-driven updates.
  • Multiple components react to the same change.

Java example​

interface Observer {
void update(int value);
}

class Subject {
private final List<Observer> observers = new ArrayList<>();
private int value;

Runnable subscribe(Observer observer) {
observers.add(observer);
return () -> observers.remove(observer);
}

void setValue(int value) {
this.value = value;
observers.forEach(observer -> observer.update(this.value));
}
}

TypeScript example​

type Observer = (value: number) => void;

class Subject {
private observers: Observer[] = [];
private value = 0;

subscribe(observer: Observer): () => void {
this.observers.push(observer);
return () => {
this.observers = this.observers.filter(current => current !== observer);
};
}

setValue(value: number): void {
this.value = value;
this.observers.forEach(observer => observer(this.value));
}
}

Pros and cons​

Pros:

  • Loose coupling between subject and observers.
  • Easy to add new listeners.

Cons:

  • Hard to debug update order.
  • Potential memory leaks from subscriptions.

Common pitfalls​

  • Forgetting to unsubscribe.
  • Triggering cascading updates unintentionally.