デザインパターンに関する雑談 (15) — オブザーバーパターン
コラム紹介
カラムアドレス
コラム紹介
主に現在市場に出回っている23種類の一般的なデザインパターンを一つ一つ分析してまとめていますので、興味のある方はぜひご覧ください、また随時更新していきます。皆さんが私を監督し、一緒に学び、進歩できることを願っています。
オブザーバーパターン
オブザーバー パターンは、複数のオブザーバー オブジェクトが特定のトピック オブジェクトを同時に監視できるようにする 1 対多の依存関係を定義する動作設計パターンです。トピック オブジェクトが変更されると、そのすべてのオブザーバーが通知を受け、自身を更新します。
本旨
観測者と観測対象間の依存関係を切り離し、相互に独立して変更できるようにします。オブザーバーは、オブザーバーが特定のインターフェイスを実装していることだけを知っていればよく、特定のオブザーバー クラスを知る必要はありません。同様に、オブザーバーは、オブザーバーが特定のインターフェイスを実装していることだけを知っていればよく、特定のオブザーバーを知る必要はありません。クラスです。
主人公
主題
オブザーバーの登録、オブザーバーの削除、オブザーバーへの通知のメソッドなど、オブザーバーのインターフェイスを定義します。
ConcreteSubject (特定のオブザーバー)
監視対象のインターフェイスを実装し、オブザーバーのリストを維持し、状態が変化したときにオブザーバーに通知します。
観察者
オブザーバーのインターフェイスを定義します。これには、オブザーバーから通知を受信するための更新メソッドが含まれます。
ConcreteObserver (コンクリートオブザーバー)
オブザーバーインターフェイスを実装し、具体的には update メソッドを実装し、オブザーバーから通知を受信したときに対応する処理を実行します。
Javaプログラムの実装
// 定义观察者接口
interface Observer {
void update(String message);
}
// 定义被观察者接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String message);
}
// 具体观察者类
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
// 具体被观察者类
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
// 测试代码
public class ObserverPatternExample {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.notifyObservers("Hello, observers!");
subject.removeObserver(observer2);
subject.notifyObservers("Observer 2 has been removed!");
}
}
出力結果
Observer 1 received message: Hello, observers!
Observer 2 received message: Hello, observers!
Observer 1 received message: Observer 2 has been removed!
プログラム分析
上の例では、オブザーバー インターフェイス (Observer) と監視対象インターフェイス (Subject) を定義しました。具象オブザーバー クラス (ConcreteObserver) と具象オブザーバー クラス (ConcreteSubject) は、対応するインターフェイスを実装します。
メリットとデメリットの分析
アドバンテージ
デカップリング
オブザーバー パターンは、オブザーバーとオブザーバー間の依存関係を切り離し、独立して変更できるようにします。観察対象が変化した場合、どの観察者が存在するかを知らなくても、観察者に通知するだけで済みます。
スケーラビリティ
オブザーバー パターンを使用すると、監視対象のコードを変更することなく、新しいオブザーバーを簡単に追加できます。これはオープンクローズの原則に準拠しており、システムの柔軟性と拡張性が向上します。
1対多の関係
オブザーバー パターンは 1 対多の依存関係を実装でき、監視対象オブジェクトは複数のオブザーバーを持つことができます。イベント監視やメッセージ購読などの機能を簡単に実装できます。
欠点がある
観察者が多すぎる
オブザーバが多すぎると、オブザーバがオブザーバに通知するまでに時間がかかり、システムのパフォーマンスに影響を与える可能性があります。
循環依存関係
オブザーバーとオブザーバーの間に循環依存関係がある場合、システムにデッドロックなどの問題が発生する可能性があります。
更新注文の問題
オブザーバー パターン内のオブザーバーの更新順序は定義されていないため、オブザーバー間の依存関係で問題が発生する可能性があります。
要約する
システムの柔軟性と拡張性を向上させることができます。しかし同時に、システムの安定性とパフォーマンスを確保するために、オブザーバーの多さ、循環依存関係、更新順序などの問題にも注意を払う必要があります。オブザーバー パターンを使用する場合、特定のシナリオとニーズに基づいてトレードオフと設計を行う必要があります。