オブザーバーパターン
オブザーバーパターン(Observer Pattern) は、あるオブジェクト(サブジェクト)の状態が変化したときに、その変化を他のオブジェクト(オブザーバー)に通知するデザインパターンです。このパターンは、1対多の依存関係を構築し、サブジェクトとオブザーバーの間の疎結合を実現するのに役立ちます。
たとえば、SNSの通知システムや、ユーザーインターフェースのリアルタイム更新など、状態の変更を複数のオブジェクトに伝える必要がある場面で使用されます。
TypeScriptでのオブザーバーパターンの実装
以下に、TypeScriptを使ったオブザーバーパターンの実装例を紹介します。
天気の変化を監視する例
typescript
// Observer インターフェース
interface Observer {
update(temperature: number): void;
}
// Subject インターフェース
interface Subject {
addObserver(observer: Observer): void;
removeObserver(observer: Observer): void;
notifyObservers(): void;
}
// WeatherStation クラス(サブジェクト)
class WeatherStation implements Subject {
private observers: Observer[] = [];
private temperature: number = 0;
addObserver(observer: Observer): void {
this.observers.push(observer);
}
removeObserver(observer: Observer): void {
this.observers = this.observers.filter(obs => obs !== observer);
}
setTemperature(temp: number): void {
console.log(`WeatherStation: 新しい温度は ${temp} 度です。`);
this.temperature = temp;
this.notifyObservers();
}
notifyObservers(): void {
for (const observer of this.observers) {
observer.update(this.temperature);
}
}
}
// TemperatureDisplay クラス(オブザーバー)
class TemperatureDisplay implements Observer {
update(temperature: number): void {
console.log(`TemperatureDisplay: 現在の温度は ${temperature} 度です。`);
}
}
// Fan クラス(オブザーバー)
class Fan implements Observer {
update(temperature: number): void {
if (temperature > 25) {
console.log('Fan: 暑いのでファンをオンにします。');
} else {
console.log('Fan: 涼しいのでファンをオフにします。');
}
}
}
// 実際の使用例
const weatherStation = new WeatherStation();
const tempDisplay = new TemperatureDisplay();
const fan = new Fan();
// オブザーバーを登録
weatherStation.addObserver(tempDisplay);
weatherStation.addObserver(fan);
// 温度を変更し、通知を送信
weatherStation.setTemperature(20);
weatherStation.setTemperature(30);
解説
Observerインターフェース
Observer
インターフェースは、すべてのオブザーバーが実装する必要があるupdate
メソッドを定義します。これにより、異なるオブザーバーでも共通のインターフェースで通知を受け取ることができます。
Subjectインターフェース
Subject
インターフェースは、オブザーバーを追加・削除するためのメソッドや、オブザーバーに通知するnotifyObservers
メソッドを定義します。
WeatherStationクラス(サブジェクト)
WeatherStation
クラスは、Subject
インターフェースを実装し、内部にオブザーバーのリストを保持します。温度が変更されると、notifyObservers
メソッドを通じてすべてのオブザーバーに通知します。
TemperatureDisplayクラスとFanクラス(オブザーバー)
TemperatureDisplay
とFan
は、Observer
インターフェースを実装しており、温度が変更された際にupdate
メソッドを通じて通知を受け取ります。
サブジェクトとオブザーバーの連携
weatherStation.addObserver(tempDisplay)
のようにしてオブザーバーを登録します。温度が変更されると、notifyObservers
メソッドが呼び出され、すべての登録されたオブザーバーに通知が送られます。
利点
- 疎結合: サブジェクトとオブザーバー間の依存関係が緩くなるため、オブジェクトの変更が他のオブジェクトに与える影響を最小限に抑えられます。
- 拡張性: 新しいオブザーバーを追加するのが簡単です。サブジェクトに変更を加えることなく、新しいオブザーバーを追加して通知を受け取ることができます。
使用例
- イベントリスナー: UIのボタンをクリックした際に複数のリスナーに通知を送る場合など、イベント駆動型プログラミングにおいてよく使われます。
- リアルタイムデータ更新: 天気アプリや株価監視アプリなど、状態の変更をリアルタイムで複数の箇所に通知する必要がある場合に適しています。
まとめ
オブザーバーパターンは、オブジェクト間の依存関係を効率的に管理し、状態の変化を複数のオブジェクトに通知するための強力な手段です。TypeScriptを使うことで、インターフェースを用いてオブジェクトの型を定義し、より堅牢で可読性の高いコードを実現できます。
このパターンを理解し、適切な場面で使うことで、コードの保守性と拡張性が向上し、動的な状態変化を効率的に扱えるようになります。