Bird
Raised Fist0
LLDsystem_design~7 mins

Observer pattern in LLD - System Design Guide

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Problem Statement
When multiple parts of a system need to stay updated about changes in another part, manually notifying each part leads to tightly coupled code and missed updates. This causes bugs and makes the system hard to maintain or extend.
Solution
The Observer pattern lets an object (the subject) keep a list of dependents (observers) and automatically notify them of any state changes. Observers register themselves to the subject and receive updates without the subject needing to know their details, reducing coupling.
Architecture
Subject
Observer1
Observer2
no
Observers

This diagram shows a Subject holding references to multiple Observers. Observers register to the Subject, and when the Subject's state changes, it notifies all registered Observers.

Trade-offs
✓ Pros
Decouples subject and observers, allowing independent development and reuse.
Supports dynamic addition and removal of observers at runtime.
Simplifies communication when multiple components need updates from one source.
✗ Cons
Can lead to memory leaks if observers are not properly unregistered.
Notification order is not guaranteed, which may cause inconsistent states.
Too many observers can cause performance overhead during notifications.
Use when multiple components need to react to changes in another component's state, especially in event-driven or UI systems with moderate to high update frequency.
Avoid when the number of observers is very large (thousands+) causing performance issues, or when strict notification order and timing guarantees are required.
Real World Examples
Amazon
Amazon uses the Observer pattern in their order processing system to notify inventory, shipping, and billing services when an order status changes.
Twitter
Twitter uses the Observer pattern to update followers' timelines when a user posts a new tweet.
LinkedIn
LinkedIn applies the Observer pattern to notify users about connection requests, messages, and profile updates in real time.
Code Example
The before code tightly couples the Subject to specific observers, requiring manual calls to each observer. The after code uses the Observer pattern where Subject maintains a list of observers and notifies them automatically on state changes, allowing easy addition or removal of observers.
LLD
### Before: Without Observer Pattern
class Subject:
    def __init__(self):
        self.state = None
        self.observer1 = None
        self.observer2 = None

    def set_state(self, state):
        self.state = state
        if self.observer1:
            self.observer1.update(state)
        if self.observer2:
            self.observer2.update(state)

class Observer1:
    def update(self, state):
        print(f"Observer1: State updated to {state}")

class Observer2:
    def update(self, state):
        print(f"Observer2: State updated to {state}")

subject = Subject()
subject.observer1 = Observer1()
subject.observer2 = Observer2()
subject.set_state('ON')


### After: With Observer Pattern
class Subject:
    def __init__(self):
        self._observers = []
        self._state = None

    def register(self, observer):
        self._observers.append(observer)

    def unregister(self, observer):
        self._observers.remove(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self._state)

    def set_state(self, state):
        self._state = state
        self.notify()

class Observer:
    def update(self, state):
        print(f"Observer: State updated to {state}")

subject = Subject()
observer1 = Observer()
observer2 = Observer()
subject.register(observer1)
subject.register(observer2)
subject.set_state('ON')
OutputSuccess
Alternatives
Publish-Subscribe
Uses a message broker to decouple publishers and subscribers, allowing asynchronous communication and topic-based filtering.
Use when: Choose when you need loose coupling across distributed systems or asynchronous event handling.
Callback Functions
Directly passes a function to be called on an event, tightly coupling the caller and callee.
Use when: Choose for simple, synchronous event handling within a single component or module.
Summary
Observer pattern helps keep multiple parts of a system updated automatically when one part changes.
It reduces tight coupling by letting observers register and receive updates without the subject knowing their details.
This pattern is useful in event-driven systems but requires careful management of observer registration and notification order.

Practice

(1/5)
1.

What is the main purpose of the Observer pattern in system design?

easy
A. To create a strict hierarchy of classes
B. To allow objects to automatically update when another object changes
C. To store data in a database
D. To improve the speed of a single function

Solution

  1. Step 1: Understand the Observer pattern role

    The Observer pattern is designed to let one object notify others about changes automatically.
  2. Step 2: Match purpose with options

    To allow objects to automatically update when another object changes correctly describes automatic updates between objects without tight coupling.
  3. Final Answer:

    To allow objects to automatically update when another object changes -> Option B
  4. Quick Check:

    Observer pattern = automatic updates [OK]
Hint: Observer means automatic update on change [OK]
Common Mistakes:
  • Confusing Observer with data storage
  • Thinking it creates class hierarchies
  • Assuming it improves function speed
2.

Which of the following is the correct way to register an observer in the Observer pattern?

subject = Subject()
observer = ConcreteObserver()
# What code registers the observer?
easy
A. subject.addObserver(observer)
B. observer.subscribe(subject)
C. observer.register(subject)
D. subject.attach(observer)

Solution

  1. Step 1: Recall common Observer pattern method names

    Typically, the subject has a method named attach or addObserver to register observers.
  2. Step 2: Identify the most standard method

    While addObserver is used in some languages, attach is the classic and widely accepted method name.
  3. Final Answer:

    subject.attach(observer) -> Option D
  4. Quick Check:

    Register observer = subject.attach(observer) [OK]
Hint: Subject.attach(observer) is classic registration [OK]
Common Mistakes:
  • Calling register on observer instead of subject
  • Using subscribe which is not standard here
  • Confusing addObserver with observer methods
3.

Given this code snippet, what will be printed?

class Subject:
    def __init__(self):
        self.observers = []
        self.state = 0
    def attach(self, observer):
        self.observers.append(observer)
    def set_state(self, state):
        self.state = state
        for obs in self.observers:
            obs.update(state)

class Observer:
    def __init__(self, name):
        self.name = name
    def update(self, state):
        print(f"{self.name} received state {state}")

subject = Subject()
obs1 = Observer('A')
obs2 = Observer('B')
subject.attach(obs1)
subject.attach(obs2)
subject.set_state(5)
medium
A. A received state 5 B received state 5
B. A received state 0 B received state 0
C. No output
D. Error: update method missing

Solution

  1. Step 1: Follow the attach and set_state calls

    Observers A and B are attached to the subject. When set_state(5) is called, it updates the state and calls update(5) on each observer.
  2. Step 2: Understand the update method output

    Each observer prints its name and the new state, so both print lines with state 5.
  3. Final Answer:

    A received state 5 B received state 5 -> Option A
  4. Quick Check:

    Observers print updated state 5 [OK]
Hint: Observers print on update call with new state [OK]
Common Mistakes:
  • Thinking observers print old state
  • Assuming no output without explicit print
  • Confusing method names causing errors
4.

Identify the bug in this Observer pattern implementation:

class Subject:
    def __init__(self):
        self.observers = set()
    def attach(self, observer):
        self.observers.add(observer)
    def notify(self):
        for obs in self.observers:
            obs.update()

class Observer:
    def update(self, state):
        print(f"State updated to {state}")

subject = Subject()
obs = Observer()
subject.attach(obs)
subject.notify()
medium
A. Observer.update requires a state argument but notify calls without it
B. Subject.observers should be a list, not a set
C. attach method should remove observers, not add
D. notify method should not call update

Solution

  1. Step 1: Check method signatures and calls

    The Observer's update method expects a state argument, but notify calls update() without any argument.
  2. Step 2: Identify mismatch causing error

    This mismatch will cause a runtime error due to missing required positional argument.
  3. Final Answer:

    Observer.update requires a state argument but notify calls without it -> Option A
  4. Quick Check:

    Method argument mismatch causes error [OK]
Hint: Check method parameters match calls exactly [OK]
Common Mistakes:
  • Ignoring missing argument errors
  • Thinking sets are invalid for observers
  • Misunderstanding attach method purpose
5.

You are designing a stock price alert system using the Observer pattern. Multiple clients want updates only when the stock price changes by more than 5%. How should you modify the Observer pattern to handle this efficiently?

hard
A. Make observers poll the Subject periodically for changes
B. Notify all observers on every price change regardless of amount
C. Add a threshold check in the Subject before notifying observers
D. Remove the Observer pattern and use direct method calls

Solution

  1. Step 1: Understand the requirement for selective updates

    Clients want updates only if price changes exceed 5%, so notifying on every change is inefficient.
  2. Step 2: Implement threshold logic in Subject

    Adding a check in the Subject to compare new price with old and notify observers only if change > 5% reduces unnecessary notifications.
  3. Final Answer:

    Add a threshold check in the Subject before notifying observers -> Option C
  4. Quick Check:

    Efficient notify = threshold check in Subject [OK]
Hint: Filter notifications in Subject to reduce updates [OK]
Common Mistakes:
  • Not filtering updates causing overload
  • Using polling which wastes resources
  • Removing Observer pattern loses decoupling benefits