Observer Pattern

10455 ワード

傍観者モード


1つのオブジェクトのステータスが変更されると、依存する他のオブジェクトに連絡し、データを更新することで1対多の依存性を定義します.
👀 傍観者は英語の単語で、監視者と観察者を意味する.傍観者モードでは、観察者が名前でデータを観察したり、イベントを生成したりするSubjectに対して、Subjectはイベント発生時に自分のObserverイベントの観察を通知します.
1️⃣ Observer는 Subject을 구독한다.
2️⃣ Observer에 이벤트가 발생한다.
3️⃣ Subject을 구독한 Observer에게 이벤트가 전달된다.
📄 傍観者モードは購読モードとも呼ばれ、それを新聞購読にたとえるとSubjectは新聞社となり、Observerは新聞の購読者となり、eventは新聞となる.新聞社に新聞の購読を申請すると、新聞社は新聞を発行するたびに、新聞を購読しているすべての人に新聞を送信します.

プッシュとプッシュ


Pull方式は、Observerが必要とする場合にSubjectから値を取得し、Push方式はイベント発生時にSubjectがObserverに値をプッシュする.

ファイバモードを使用する理由


では、なぜ傍観者モードを使うのでしょうか.かわいい画像で、なぜ光ファイバモードが使われているのかよく説明できます。があるので、その例を持ってきました!
🌞私たちがやりたいのは、今の天気予報、天気統計画面の天気応用です.このアプリケーションは、気象庁から提供された気象データWeatherDataのオブジェクトを受信して使用し、各画面がデータ更新後にリアルタイムで更新される.
まず、WeatherDataはこうです.
class WeatherData {
	getTemperature()
	getHumidity()
	getPressure()
	measurementsChanged()
}
getTemperaturegetHumiditygetPressureはそれぞれ温度、湿度、気圧をもたらす方法であり、measurementsChanged()は気象観測値の更新に伴って呼び出される方法である.
このオブジェクトを使用してUIを更新する必要があります.でも….

🙄 ちょっと変です。

class WeatherData {
	...
	measrementsChanged(){
		val temp = getTemperature()
		val humidity = getHumidity()
		val pressure = getPressure()
		
		currentConditionDisplay.update(temp, humidity, pressure)
		statisticDisplay.update(temp, humidity, pressure)
		forecastDisplay.update(temp, humidity, pressure)
	}
}
  • 2WeatherDataを使用するUIが追加された場合、WeatherDataのコードを変更する必要があります.
  • 以上のため、実行時に
  • に書き込むUIを追加することはできません.
  • データ変更の部分はカプセル化されていません.
  • 📌 パッケージは、外部で特定のプロパティやメソッドを使用しないように非表示にします.外部オブジェクトはカプセル化されたオブジェクトの内部構造を得ることができず、オブジェクトが公開したフィールドと方法しか使用できません.
    上記の問題を解決するために、ファイバモードはSubjectとObserverの間にインタフェースを挿入し、両者を分離する.Observerはインタフェースを継承し、イベントが発生するたびに実行されるコールバックメソッドを実現します.また,Subjectはイベントが発生するたびにインタフェースメソッドを実装する.

    😌 ファイバアレイの適用


    Subject Pseudo code
    interface Subject {
    	registerObserver()
    	unregisterObserver()
    	notifyObservers()
    }
    
    class WeatherData : Subject {
    	registerObserver() {...}
    	unregisterObserver() {...}
    	notifyObservers() {
    		for (observer in observers) {
    			observer.update(t, h, p)
    			}
    	}
    	measurementsChanged(){
    		notifyObservers()
    	}
    }
    Observer Pseudo code
    interface Observer {
    	update()
    }
    
    class currentConditionDisplay: Observer {
    	update(temperature, humidity, pressure){
    		updateUI()
    	}
    	updateUI()
    }
    class statisticDisplay: Observer {...}
    class forecastDisplay: Observer {...}

    ファイバモードの構造



    これは、上記の例で短い傍観者モードの構造である.Subjectには、登録されているObserverリストやWeatherDataregisterObserver()などの傍観者オブジェクトを追加または削除する方法があります.Subjectにイベントが発生した場合、unregisterObserver()メソッドが呼び出され、リスト内の傍観者オブジェクトにイベントが発生したことが通知される.
    Observerは、notifyObservers()メソッドを有するインターフェースである.実際の観察者は、観察者インタフェースを実現するグラフ中のupdateである.

    ルースカップリング


    傍観者モードでのポイントはSubjectとObserverのインタフェースを接続することである.インタフェースはSubjectオブジェクトとObserverオブジェクトをばらばらに結合させる.
    2つのオブジェクトがばらばらに結合するという意味は、2つのオブジェクトが相互作用しているが、互いに理解していないことを意味する.SubjectとObserverは傍観者モードでどれだけ互いに理解していないのか、これはどんなメリットをもたらしますか?🤔
  • SubjectはObserverのインタフェースしか知らない.
  • Observerはいつでも追加、削除できます.
  • の新しい形式のオブザーバーを追加したオブザーバーはSubjectに影響しません.
  • SubjectとObserverは互いに独立して使用することができる.
  • SubjectまたはObserverが変更されても、相互に影響はありません.
  • 2つのオブジェクト間の相互依存性を最小化することで,変更に柔軟に対応できる.💨

    TL;DR


    傍観者モードによりSubjectとObserverの依存性を減少させることができる.

    REF


    [デザインモード]2。ファイバモードの概念と例(observer pattern)
    Head First:Design Patterns-第2話:Observerモード
    傍観者モードの概念を伝える
    ファイバ・モードの整理(observer pattern)