- Published on
Design Patterns: Observer
- Authors
- Name
- Loi Tran
Introduction
Purpose: One-to-many relationship where one change is observed and triggers updates to its dependents.
Use Cases: Event handling, email notifications, live updates.
from abc import ABC, abstractmethod
# Subject
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):
for observer in self._observers:
observer.update()
# Observer
class Observer(ABC):
@abstractmethod
def update(self):
pass
# Concrete Observers
class ConcreteObserverA(Observer):
def update(self):
print("Observer A: Reacted to the event.")
class ConcreteObserverB(Observer):
def update(self):
print("Observer B: Reacted to the event.")
# Usage
subject = Subject()
observer_a = ConcreteObserverA()
observer_b = ConcreteObserverB()
subject.attach(observer_a)
subject.attach(observer_b)
subject.notify() # Both observers react
subject.detach(observer_a)
subject.notify() # Only Observer B reacts
// Subject
class Subject {
constructor() {
this.observers = [];
}
attach(observer) {
this.observers.push(observer);
}
detach(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify() {
this.observers.forEach(observer => observer.update());
}
}
// Observer
class Observer {
update() {
throw new Error("Method 'update()' must be implemented.");
}
}
// Concrete Observers
class ConcreteObserverA extends Observer {
update() {
console.log("Observer A: Reacted to the event.");
}
}
class ConcreteObserverB extends Observer {
update() {
console.log("Observer B: Reacted to the event.");
}
}
// Usage
const subject = new Subject();
const observerA = new ConcreteObserverA();
const observerB = new ConcreteObserverB();
subject.attach(observerA);
subject.attach(observerB);
subject.notify(); // Both observers react
subject.detach(observerA);
subject.notify(); // Only Observer B reacts
// Subject
class Subject {
final List<Observer> _observers = [];
void attach(Observer observer) {
_observers.add(observer);
}
void detach(Observer observer) {
_observers.remove(observer);
}
void notify() {
for (var observer in _observers) {
observer.update();
}
}
}
// Observer
abstract class Observer {
void update();
}
// Concrete Observers
class ConcreteObserverA implements Observer {
void update() {
print("Observer A: Reacted to the event.");
}
}
class ConcreteObserverB implements Observer {
void update() {
print("Observer B: Reacted to the event.");
}
}
// Usage
void main() {
final subject = Subject();
final observerA = ConcreteObserverA();
final observerB = ConcreteObserverB();
subject.attach(observerA);
subject.attach(observerB);
subject.notify(); // Both observers react
subject.detach(observerA);
subject.notify(); // Only Observer B reacts
}
# Subject
class Subject
def initialize
@observers = []
end
def attach(observer)
@observers << observer
end
def detach(observer)
@observers.delete(observer)
end
def notify
@observers.each(&:update)
end
end
# Observer
class Observer
def update
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
# Concrete Observers
class ConcreteObserverA < Observer
def update
puts "Observer A: Reacted to the event."
end
end
class ConcreteObserverB < Observer
def update
puts "Observer B: Reacted to the event."
end
end
# Usage
subject = Subject.new
observer_a = ConcreteObserverA.new
observer_b = ConcreteObserverB.new
subject.attach(observer_a)
subject.attach(observer_b)
subject.notify # Both observers react
subject.detach(observer_a)
subject.notify # Only Observer B reacts