Observer Pattern

  • Sprouting
  • c.

The observer pattern is a behavioral design pattern for defining a publisher/subscriber relationship to notify multiple “subscribed” objects about “published” events.

Example

Real-world analogy: a magazine with subscribed readers

design-patterns/src/behavioral/observer.ts at main

Publisher

A magazine allows readers to subscribe. Whenever a new issue is published, the magazine sends the new issue to each of the subscribed readers. If a reader unsubscribes from the magazine, they will no longer be sent published issues.

class Magazine {
private issue: number;
private readers: Reader[];
constructor() {
this.issue = 0;
this.readers = [];
}
subscribe(reader: Reader) {
if (this.readers.indexOf(reader) !== -1) return;
this.readers.push(reader);
}
unsubscribe(reader: Reader) {
const index = this.readers.indexOf(reader);
if (index === -1) return;
this.readers.splice(index, 1);
}
publishIssue() {
this.issue += 1;
this.notifyReaders();
}
private notifyReaders() {
this.readers.forEach((reader) => reader(this.issue));
}
}

Subscriber

Once a reader is subscribed to the magazine, they are notified about each published issue.

type Reader = (issue: number) => void;
const readerA: Reader = (issue) => console.log(`A: received issue ${issue}`);
const readerB: Reader = (issue) => console.log(`B: received issue ${issue}`);

Client

The client subscribes and unsubscribes readers to the magazine. Calling the magazine’s publishIssue method sends the subscribed readers the next issue of the magazine.

const magazine = new Magazine();
magazine.subscribe(readerA);
magazine.publishIssue();
// Expected output:
// A: received issue 1
magazine.subscribe(readerB);
magazine.publishIssue();
// Expected output:
// A: received issue 2
// B: received issue 2
magazine.unsubscribe(readerA);
magazine.publishIssue();
// Expected output:
// B: received issue 3
magazine.unsubscribe(readerB);
magazine.publishIssue();
// Expected output:

Backlinks