Introduction
The Observer pattern is a behavioral design pattern that defines a one-to-many dependency between objects. When the state of one object (the subject) changes, all its dependent objects (observers) are automatically notified and updated. This pattern promotes loose coupling, allowing objects to interact without needing to know the details of each other’s implementation.
Purpose
One-to-many relationship where one change is observed and triggers updates to its dependents.
Use Cases
- Event handling
- Email notifications
- Live updates.
1from abc import ABC, abstractmethod2 3# Subject4class Subject:5 def __init__(self):6 self._observers = []7 8 def attach(self, observer):9 self._observers.append(observer)10 11 def detach(self, observer):12 self._observers.remove(observer)13 14 def notify(self):15 for observer in self._observers:16 observer.update()17 18# Observer19class Observer(ABC):20 @abstractmethod21 def update(self):22 pass23 24# Concrete Observers25class ConcreteObserverA(Observer):26 def update(self):27 print("Observer A: Reacted to the event.")28 29class ConcreteObserverB(Observer):30 def update(self):31 print("Observer B: Reacted to the event.")32 33# Usage34subject = Subject()35observer_a = ConcreteObserverA()36observer_b = ConcreteObserverB()37 38subject.attach(observer_a)39subject.attach(observer_b)40 41subject.notify() # Both observers react42subject.detach(observer_a)43subject.notify() # Only observer B reacts1// Subject2class Subject {3 constructor() {4 this.observers = [];5 }6 7 attach(observer) {8 this.observers.push(observer);9 }10 11 detach(observer) {12 this.observers = this.observers.filter(obs => obs !== observer);13 }14 15 notify() {16 this.observers.forEach(observer => observer.update());17 }18}19 20// Observer21class Observer {22 update() {23 throw new Error("Method 'update()' must be implemented.");24 }25}26 27// Concrete Observers28class ConcreteObserverA extends Observer {29 update() {30 console.log("Observer A: Reacted to the event.");31 }32}33 34class ConcreteObserverB extends Observer {35 update() {36 console.log("Observer B: Reacted to the event.");37 }38}39 40// Usage41const subject = new Subject();42const observerA = new ConcreteObserverA();43const observerB = new ConcreteObserverB();44 45subject.attach(observerA);46subject.attach(observerB);47 48subject.notify(); // Both observers react49subject.detach(observerA);50subject.notify(); // Only Observer B reacts1// Subject2class Subject {3 final List<Observer> _observers = [];4 5 void attach(Observer observer) {6 _observers.add(observer);7 }8 9 void detach(Observer observer) {10 _observers.remove(observer);11 }12 13 void notify() {14 for (var observer in _observers) {15 observer.update();16 }17 }18}19 20// Observer21abstract class Observer {22 void update();23}24 25// Concrete Observers26class ConcreteObserverA implements Observer {27 28 void update() {29 print("Observer A: Reacted to the event.");30 }31}32 33class ConcreteObserverB implements Observer {34 35 void update() {36 print("Observer B: Reacted to the event.");37 }38}39 40// Usage41void main() {42 final subject = Subject();43 final observerA = ConcreteObserverA();44 final observerB = ConcreteObserverB();45 46 subject.attach(observerA);47 subject.attach(observerB);48 49 subject.notify(); // Both observers react50 subject.detach(observerA);51 subject.notify(); // Only Observer B reacts52}1# Subject2class Subject3 def initialize4 @observers = []5 end6 7 def attach(observer)8 @observers << observer9 end10 11 def detach(observer)12 @observers.delete(observer)13 end14 15 def notify16 @observers.each(&:update)17 end18end19 20# Observer21class Observer22 def update23 raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"24 end25end26 27# Concrete Observers28class ConcreteObserverA < Observer29 def update30 puts "Observer A: Reacted to the event."31 end32end33 34class ConcreteObserverB < Observer35 def update36 puts "Observer B: Reacted to the event."37 end38end39 40# Usage41subject = Subject.new42observer_a = ConcreteObserverA.new43observer_b = ConcreteObserverB.new44 45subject.attach(observer_a)46subject.attach(observer_b)47 48subject.notify # Both observers react49subject.detach(observer_a)50subject.notify # Only Observer B reactsConclusion
The Observer pattern is ideal for scenarios where multiple components need to stay synchronized with a single source of truth. It is commonly used in event handling systems, GUI frameworks, messaging systems, and any situation where changes in one object should automatically propagate to others, improving maintainability and scalability.