🧩 Observer パターン
✅ 設計意図
- イベントを発火するだけで、誰がそれに反応するかを知らない
- 処理の追加・変更が容易(リスナーの追加だけで OK)
✅ 適用理由
- 通知先を動的に追加・差し替え可能
- 処理ごとにクラスを分離でき、テスト・再利用性が高い
✅ 向いているシーン
- イベントの発生とその反応処理を分離したいとき
- 拡張や通知の追加が今後も増える場合
✅ コード例
- TypeScript
- PHP
- Python
// Observer インターフェース
interface Observer {
update(email: string): void;
}
// ConcreteObserver
class Mailer implements Observer {
update(email: string): void {
console.log(`送信しました: ${email} → ようこそ!`);
}
}
// Subject(通知元)
class UserService {
private observers: Observer[] = [];
addObserver(observer: Observer): void {
this.observers.push(observer);
}
notifyObservers(email: string): void {
this.observers.forEach((observer) => observer.update(email));
}
registerUser(email: string): void {
console.log(`ユーザー登録: ${email}`);
this.notifyObservers(email);
}
}
// 利用例
const service = new UserService();
service.addObserver(new Mailer());
service.registerUser("user@example.com");
<?php
interface Observer {
public function update(string $email): void;
}
class Mailer implements Observer {
public function update(string $email): void {
echo "送信しました: {$email} → ようこそ!\n";
}
}
class UserService {
/** @var Observer[] */
private array $observers = [];
public function addObserver(Observer $observer): void {
$this->observers[] = $observer;
}
private function notifyObservers(string $email): void {
foreach ($this->observers as $observer) {
$observer->update($email);
}
}
public function registerUser(string $email): void {
echo "ユーザー登録: {$email}\n";
$this->notifyObservers($email);
}
}
// 利用例
$service = new UserService();
$service->addObserver(new Mailer());
$service->registerUser("user@example.com");
from abc import ABC, abstractmethod
class Observer(ABC):
@abstractmethod
def update(self, email: str):
pass
class Mailer(Observer):
def update(self, email: str):
print(f"送信しました: {email} → ようこそ!")
class UserService:
def __init__(self):
self._observers: list[Observer] = []
def add_observer(self, observer: Observer):
self._observers.append(observer)
def _notify_observers(self, email: str):
for observer in self._observers:
observer.update(email)
def register_user(self, email: str):
print(f"ユーザー登録: {email}")
self._notify_observers(email)
# 利用例
service = UserService()
service.add_observer(Mailer())
service.register_user("user@example.com")
✅ 解説
このコードは Observer
パターン を使用して、UserService
(通知元)が複数の Observer
(通知先)に対してイベントを通知する設計を実現している。
Observer
パターンは、オブジェクト間の 1 対多の依存関係を定義し、1 つのオブジェクトの状態が変化した際に、依存するすべてのオブジェクトに通知を送るデザインパターン。
1. Observer パターンの概要
- Subject: 通知元となるオブジェクト。
Observer
を登録・削除し、イベント発生時に通知を送る- このコードでは
UserService
が該当
- このコードでは
- Observer: 通知を受け取るオブジェクトのインターフェース
- このコードでは
Observer
が該当
- このコードでは
- ConcreteObserver:
Observer
を実装し、通知を受け取った際の具体的な処理を定義- このコードでは
Mailer
が該当
- このコードでは
2. 主なクラスとその役割
Observer
- 通知を受け取るための共通インターフェース
update(email: string): void
メソッドを定義
Mailer
- Observer を実装した具体的な通知先
update
メソッドで通知を受け取り、メール送信処理を実行
UserService
- 通知元(
Subject
) addObserver
メソッドでObserver
を登録notifyObservers
メソッドで登録されたすべてのObserver
に通知を送信registerUser
メソッドでユーザー登録処理を行い、通知を送信
- 通知元(
3. UML クラス図
4. Observer パターンの利点
- 疎結合:
Subject
とObserver
が疎結合であるため、Observer
を追加・削除してもSubject
に影響を与えない - 拡張性: 新しい
Observer
を追加する場合も、Observer
インターフェースを実装するだけで対応可能 - リアルタイム通知: 状態の変化をリアルタイムで通知可能
この設計は、イベント駆動型のシステムや、複数のオブジェクトに対して状態変化を通知する必要がある場面で非常に有効であり、 コードの拡張性と保守性を向上させる。