Bird
0
0
LLDsystem_design~7 mins

Observer pattern in LLD - System Design Guide

Choose your learning style9 modes available
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.