python-design-pattern-rag

The Observer Pattern (Behavioral)

Purpose

The Observer pattern defines a one-to-many relationship between objects. When one object (the subject) changes state, it automatically notifies all its dependents (observers). This pattern is commonly used in event-driven systems to keep different parts of a program in sync.

Problem It Solves

In many applications, multiple parts need to respond to changes in another part. For example, when a user updates a setting, other parts of the app might need to react. Hardcoding these relationships creates tight coupling, which makes the system hard to maintain. The Observer pattern solves this by allowing objects to subscribe to changes without needing direct links.

When to Use It

Use this pattern when:

When Not to Use It

Avoid this pattern if:

How It Works

The pattern involves three core components:

  1. Subject – Maintains a list of observers and notifies them when its state changes.
  2. Observer – Defines an update() method that receives notifications.
  3. Concrete Observer – Implements update() and responds to changes in the subject.

Real-World Analogy

Think of a magazine subscription. When you subscribe, you receive each new issue automatically. The publisher is the subject. You, the subscriber, are the observer. A concrete observer might be your email or mailbox receiving the update.

Simplified Example

Here’s a basic implementation in Python:

class Subject:
    def __init__(self):
        self._observers = []

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

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

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

class Observer:
    def update(self, message):
        pass

class ConcreteObserver(Observer):
    def __init__(self, name):
        self._name = name

    def update(self, message):
        print(f"{self._name} received: {message}")

# Usage
subject = Subject()
observer1 = ConcreteObserver("Observer 1")
observer2 = ConcreteObserver("Observer 2")

subject.attach(observer1)
subject.attach(observer2)

subject.notify("State has changed")

subject.detach(observer1)
subject.notify("Another change occurred")

In this example:

Learn More

Explore the full implementation here: Observer Pattern – Python Example