BEHAVIORAL PATTERNS / OBJECT DESIGN BRIEF

Observer pattern

The Observer pattern lets an object (the subject) notify a list of dependents (observers) automatically when its state changes.

BeginnerPhase 06 / Topic 2 of 10ResponsibilitiesCollaborationsExtensibility
01

Overview

The Observer pattern lets an object (the subject) notify a list of dependents (observers) automatically when its state changes. The subject only knows that observers implement an update interface; it does not know what they do.

It is the foundation of event listeners in the browser, reactive UI frameworks, pub/sub systems, and domain events. It decouples the thing that changes from the things that react.

A YouTube subscription

When a channel uploads a video, every subscriber is notified. The channel does not know or care whether you watch on a phone or a TV. You can subscribe or unsubscribe at any time.

02

When to use it

  • A change in one object must trigger actions in others, and the set of reactions changes over time.
  • You want to add reactions such as email, analytics, or cache invalidation without editing the core logic.
  • Several UI components must stay in sync with one model.
03

Where it shows up in interviews

Event notifications

Recognize it when: one change must notify many dependents.

  • Design a stock price alert system
  • Design a notification service
  • Design a parking lot display board
Decoupled reactions

Recognize it when: adding reactions should not change the source.

  • Design an order pipeline
  • Design a weather station
04

Where it is used in real software

DOM events

addEventListener lets many handlers observe clicks and input.

RxJS and reactive streams

Observables push values to subscribers.

Spring ApplicationEvents

Beans publish events that listeners handle without direct coupling.

05

Key terms

Subject
The object being watched; keeps a list of observers.
Observer
An object that implements update(event).
Subscribe / unsubscribe
Adding or removing an observer from the list.
Push vs pull
Push sends data with the notification; pull lets observers query the subject.
06

How it works

  1. 1
    Define the observer interface

    For example, OrderObserver.onOrderPlaced(order).

  2. 2
    Keep a list in the subject

    The subject exposes subscribe and unsubscribe methods.

  3. 3
    Change state and notify

    After a state change, the subject loops through observers and calls their method.

  4. 4
    Observers react independently

    Email, inventory, and analytics each handle the event their own way.

07

Order placed event

OrderService places an order; three observers react

Step 1 / 3
ObserverReactionCan be added without editing OrderService?
EmailObserverSend confirmation emailYes
InventoryObserverReserve stockYes
AnalyticsObserverRecord a conversionYes

NOWObserver: EmailObserver | Reaction: Send confirmation email | Can be added without editing OrderService?: Yes

OrderService only calls notify. A new LoyaltyPointsObserver can be registered with one line and no changes to order logic.

08

Implementation

interface OrderObserver {  onOrderPlaced(order: Order): void;} class OrderService {  private observers = new Set<OrderObserver>();   subscribe(observer: OrderObserver): () => void {    this.observers.add(observer);    return () => this.observers.delete(observer); // unsubscribe handle  }   placeOrder(order: Order): void {    // ... validate and persist ...    for (const observer of this.observers) {      try {        observer.onOrderPlaced(order);      } catch (error) {        console.error("Observer failed", error); // one failure must not stop others      }    }  }} class EmailObserver implements OrderObserver {  onOrderPlaced(order: Order) {    mailer.send(order.customerEmail, `Order ${order.id} confirmed`);  }} const service = new OrderService();service.subscribe(new EmailObserver());service.subscribe({ onOrderPlaced: (order) => analytics.track("purchase", order.total) });
09

Complexity and performance

NotifyO(observers)

Each observer is called once per event.

SubscribeO(1)

With a set or list.

10

Trade-offs

Hidden control flow

It is harder to see what happens after a change because reactions are registered elsewhere. Document events and keep observers small.

Synchronous by default

A slow observer slows the subject. For slow work, publish to a queue and process asynchronously.

Order is not guaranteed

Observers should not depend on each other's execution order.

11

Variants and related techniques

Event emitter

Observers subscribe by event name: on('placed', handler).

Pub/sub

A broker sits between publishers and subscribers, so they do not reference each other at all.

Reactive streams

RxJS and similar libraries treat events as streams with operators like map and filter.

12

Common mistakes

  • Memory leaks from never unsubscribing.

    Fix: Return an unsubscribe function and call it when the observer is disposed.

  • One observer's exception stops the rest.

    Fix: Catch errors per observer, or dispatch asynchronously.

  • Observers modifying the subject during notification.

    Fix: Iterate over a copy of the list and avoid re-entrant updates.

13

Interview questions

Observer vs Pub/Sub?

In Observer, the subject holds direct references to observers. In pub/sub, a broker decouples them completely, which supports different processes and machines.

How would you make observers asynchronous?

Push events into a queue or event bus and have observers consume them independently, with retries for failures.

14

Practice problems

ProblemDifficultyWhat it trains
Stock price tickerEasyMultiple displays subscribe to one feed.
Notification serviceMediumEmail, SMS, push observers with user preferences.