Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Design Patterns  ›  Lesson

The Observer Pattern and the Hollywood Principle

Hollywood Principle 15 minObserver lets a subject announce events to any number of subscribed objects without knowing what they are, an everyday case of 'don't call us, we'll call you'.

The Observer Pattern and the Hollywood Principle

When a Shelfwise order ships, mark_shipped() emails the customer, adds loyalty points and records an analytics event. Each of those is a direct call inside Order, and every new request ("also notify the warehouse dashboard") adds another line to a class that should only know about orders. Observer turns this inside out.

The rule

Don't call us, we'll call you: subscribers wait, the subject announces.

That line is the Hollywood Principle: lower-level pieces do not keep calling in to ask "has anything happened?"; the higher-level piece calls them when something does. Observer is its most familiar pattern.

It has two roles:

  • Subject: keeps a list of subscribers and notifies them when an event happens.
  • Observers: register with the subject and offer one method for it to call.
class Order:
    def __init__(self, lines):
        self.lines = lines
        self.status = "paid"
        self._shipped_listeners = []

    def on_shipped(self, listener):
        self._shipped_listeners.append(listener)

    def mark_shipped(self):
        self.status = "shipped"
        for listener in self._shipped_listeners:
            listener.order_shipped(self)

order.on_shipped(receipt_mailer)
order.on_shipped(loyalty_service)
order.on_shipped(analytics)

Order no longer knows what a mailer or a loyalty service is. It knows only that listeners have an order_shipped method. A new feature subscribes itself, and Order never changes: Open/Closed again, this time through an event.

Observers are loosely coupled to the subject. You meet this shape everywhere: button click handlers in a user interface, signals in web frameworks, and, at a much larger scale, publish-subscribe messaging between services.

Two costs come with it. The flow of control is harder to follow, because the subject no longer shows who reacts. And the order in which observers run should not matter; if it does, the design needs a rethink.

The shortcut

Look for a method that finishes its own job and then calls a growing list of unrelated services. That list is a set of observers waiting to be born. The method keeps its own job and ends with one "notify".

When stock runs lowStep 1 of 4
  1. Spot the growing list

    Book.reserve() updates stock, then calls the restock planner, the "only 2 left" banner and the supplier emailer.

The trap is an observer that changes the subject in a way that fires the same event again, creating a loop that never ends.

Drills

Answer fast — trust the rule.

quick drill

What does the Hollywood Principle say?

quick drill

In Observer, what does the subject need to know about its observers?

quick drill

Shelfwise adds a warehouse dashboard that must react when orders ship. With Observer, what changes in Order?

quick drill

What is a real cost of the Observer pattern?

Remember

  • Don't call us, we'll call you: subscribers wait, the subject announces.
  • A method that ends by calling a growing list of unrelated services wants to notify observers instead.
  • Trap: observers that re-trigger the event they react to, or that depend on running order.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhen an order ships

When a Shelfwise order ships, Order.mark_shipped() currently calls the mailer, the loyalty-points service and the analytics tracker directly, and each new request adds another line. Explain how the Observer pattern changes this and how it reflects the Hollywood Principle.