オブザーバーパターン
オブジェクトの状態変化を複数の依存オブジェクトに自動通知するデザインパターン
設計パターンイベント駆動
オブザーバーパターンとは
オブザーバーパターンは、GoF デザインパターンの 1 つで、Subject (発行者) の状態変化を登録された Observer (購読者) に自動通知する仕組みである。DOM のイベントリスナー、React の再レンダリング、EventBridge がこのパターンの実装。
基本構造
type Listener<T> = (data: T) => void;
class EventEmitter<T> {
private listeners: Listener<T>[] = [];
on(listener: Listener<T>) { this.listeners.push(listener); }
off(listener: Listener<T>) { this.listeners = this.listeners.filter(l => l !== listener); }
emit(data: T) { this.listeners.forEach(l => l(data)); }
}
const emitter = new EventEmitter<string>();
emitter.on((msg) => console.log(`A: ${msg}`));
emitter.on((msg) => console.log(`B: ${msg}`));
emitter.emit('hello'); // A: hello, B: hello
実装例
| 実装 | 説明 |
|---|---|
| DOM EventListener | element.addEventListener('click', handler) |
| Node.js EventEmitter | emitter.on('data', handler) |
| React useState | 状態変更 → 再レンダリング (暗黙のオブザーバー) |
| EventBridge | イベント → ルール → ターゲット |
React での暗黙のオブザーバー
function Counter() {
const [count, setCount] = useState(0);
// setCount が呼ばれると、React が自動的に再レンダリング
// → useState は暗黙のオブザーバーパターン
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
メモリリークの防止
// ❌ リスナーの解除を忘れる → メモリリーク
useEffect(() => {
window.addEventListener('resize', handleResize);
}, []);
// ✅ クリーンアップで解除
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
オブザーバー vs Pub/Sub
| 観点 | オブザーバー | Pub/Sub |
|---|---|---|
| 結合度 | Subject が Observer を知っている | ブローカーが仲介 |
| スケール | プロセス内 | プロセス間、サービス間 |
| 例 | EventEmitter | SNS, EventBridge |
オブザーバーパターンの理解を深めるには関連書籍が参考になる。