Observer
You'll learn to
- -Implement a publisher/subscriber relationship where subjects notify observers without knowing their concrete types
- -Reason about push vs. pull observer variants and where Observer becomes the backbone of a notification system design
Observer defines a one-to-many dependency between objects, so that when one object (the subject) changes state, all its dependents (observers) are notified automatically - without the subject knowing anything concrete about who its observers are or what they do with the notification.
The Core Mechanic
class Observer(ABC):
@abstractmethod
def update(self, event: str) -> None: ...
class Subject:
def __init__(self):
self._observers: list[Observer] = []
def subscribe(self, observer: Observer) -> None:
self._observers.append(observer)
def notify_all(self, event: str) -> None:
for observer in self._observers:
observer.update(event) # subject has no idea what each observer does
class StockTicker(Subject):
def set_price(self, symbol: str, price: float) -> None:
self.notify_all(f"{symbol} is now ${price}")
class EmailAlert(Observer):
def update(self, event: str) -> None: print(f"Emailing: {event}")
class SmsAlert(Observer):
def update(self, event: str) -> None: print(f"Texting: {event}")
ticker = StockTicker()
ticker.subscribe(EmailAlert())
ticker.subscribe(SmsAlert())
ticker.set_price("AAPL", 150.0) # both subscribers notified, StockTicker never knew their typesPush vs. Pull
In the "push" variant above, the subject sends the relevant data directly in the notification (update(event)). In the "pull" variant, the subject only sends a signal that something changed, and the observer calls back into the subject to fetch whatever data it actually needs (update(subject) then observer calls subject.get_price()). Push is simpler and fits when observers usually want the same data; pull is more flexible when different observers care about different subsets of the subject's state and you want to avoid bundling everything into every notification.
Where Observer Becomes a System's Backbone
A full notification system design (a later case-study chapter) is essentially Observer at the architecture level: an event occurs (order shipped, price dropped, comment posted), and any number of decoupled channels - email, SMS, push, in-app - subscribe to be notified, without the event-producing code ever needing to know which channels exist. This is also the pattern behind most GUI event handling and behind the publish-subscribe messaging systems you would design in an HLD round - the same core idea shows up at very different scales.
A subtle failure mode: if observers are never unsubscribed when they should be (a UI component destroyed while still subscribed to a subject), the subject holds a reference that prevents garbage collection - a memory leak sometimes called a "lapsed listener" problem. A robust design needs an unsubscribe() path, not just subscribe().
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.