Skip to content
BytePatterns

Observer Pattern

Low-Level Design: lesson 7 of 10

One event, many reactions, and the source knows none of them.

Lesson 7 of 10 · 5 min

Observer Pattern

Step 1 of 12

One event, many reactions — and the source knows none of them.

The Idea

One object holds a list of callbacks. When something happens, it walks the list and calls each one, ignoring what they do and what they return. Reactions are added or removed without touching the source, which is why the list is the whole design.

Real-World Example

A factory andon cord. One worker pulls it; the line display halts, the supervisor's pager buzzes, and the parts window starts pulling a replacement. The worker sends one signal and never learns who answered it.

The Code

class Line:                                       # the subject
    def __init__(self): self.watchers = []
    def subscribe(self, fn): self.watchers.append(fn)
    def pull_cord(self, station):
        for fn in self.watchers: fn(station)      # fire and forget, in order

log = []
board = lambda s: log.append("board: halt " + s)
pager = lambda s: log.append("pager: go to " + s)

line = Line()
line.subscribe(board)
line.subscribe(pager)
line.pull_cord("weld-3")
print(log)      # ['board: halt weld-3', 'pager: go to weld-3']

Your turn

Fill in the blank.

class Bell:
  def __init__(self): self.listeners = []
  def on(self, fn): self.listeners.append(fn)
  def ring(self):
      for fn in self.listeners: ___

seen = []
b = Bell()
b.on(lambda: seen.append("a"))
b.on(lambda: seen.append("b"))
b.ring()
print(seen)      # should print ['a', 'b']

Mini quiz

1 / 3

In Observer, the subject knows: