17.java設計模式之觀察者模式
阿新 • • 發佈:2020-12-03
#### 基本需求:
* 氣象站可以將每天測量到的溫度,溼度,氣壓等等,以公告的形式釋出出去(比如釋出到自己的網站或第三方)
* 需要設計開放型API,便於其他第三方也能接入氣象站獲取資料
* 提供溫度、氣壓和溼度的介面
* 測量資料更新時,要能實時的通知給第三方
#### 傳統方案:
* 通過對需求的分析,我們可以設計一個WeatherData類,其中包含getXxx()方法,可以讓第三方接入,並得到相關資訊
* 當有資料更新時,WeatherData呼叫dataChange()方法去更新資料,當第三方獲取時,就能獲取到最新的資料,當然也可以推送
* WeatherData內部還需維護一個CurrentCondition物件,便於完成推送或通知
* UML類圖
* ![](https://img2020.cnblogs.com/blog/2093590/202012/2093590-20201203180940363-1901355016.png)
* 程式碼實現
* >```java
>public class CurrentCondition {
>
> // 被通知的物件類
>
> // 溫度
> private double temperature;
> // 壓力
> private double pressure;
> // 溼度
> private double humidity;
>
> public void update(double temperature, double pressure, double humidity) {
> this.temperature = temperature;
> this.pressure = pressure;
> this.humidity = humidity;
> display();
> }
>
> private void display() {
> System.out.println("======CurrentCondition======");
> System.out.println("溫度:" + this.temperature);
> System.out.println("壓力:" + this.pressure);
> System.out.println("溼度:" + this.humidity);
> }
>
>}
>```
>
>
* >```java
>public class WeatherData {
>
> // 天氣資料類
>
> // 溫度
> private double temperature;
> // 壓力
> private double pressure;
> // 溼度
> private double humidity;
>
> // 聚合天氣資料發生改變需要通知或者被推送的類
> private CurrentCondition currentCondition;
>
> public WeatherData(CurrentCondition currentCondition) {
> this.currentCondition = currentCondition;
> }
>
> // 將天氣資料的改變通知給需要通知或者被推送的類 被通知的類也可以通過getXxx()方法自己獲取資料
> private void dataChange() {
> currentCondition.update(this.temperature, this.pressure, this.humidity);
> }
>
> // 更改天氣資料
> public void setData(double temperature, double pressure, double humidity) {
> this.temperature = temperature;
> this.pressure = pressure;
> this.humidity = humidity;
> dataChange();
> }
>
>}
>```
>
>
* >```java
>public class Client {
> public static void main(String[] args) {
> WeatherData weatherData = new WeatherData(new CurrentCondition());
> // 更新天氣資料 就會通知應用或者第三方
> weatherData.setData(10d, 20d, 30d);
> System.out.println("======天氣情況發生變換======");
> weatherData.setData(20d, 30d, 40d);
> }
>}
>```
>
>
* 問題分析
* 其他第三方接入氣象站獲取資料問題
* 無法在執行時動態的新增第三方
* 違反了ocp原則,在WeatherData中,如果需要增加新的第三方應用,都需要建立一個對應的第三方的公告板物件,並加入到dataChange()方法中,不利於維護,也不是動態加入
#### 基本介紹:
* 當物件間存在一對多關係時,則使用觀察者模式(Observer),比如,當一個物件被修改時,則會自動通知依賴它的物件,觀察者模式屬於行為型模式
* 定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新
* 一個物件(目標物件)的狀態發生改變,所有的依賴物件(觀察者物件)都將得到通知,進行廣播通知
* 基本原理
* 觀察者模式類似訂牛奶業務 例如:奶站/氣象局:Subject 和 使用者/第三方網站:Observer
* Subject:登記註冊、移除和通知 一的一方(被觀察者)
* registerObserver 註冊
* removeObserver 移除
* notifyObservers() 通知所有的註冊的使用者,根據不同需求,可以是更新資料,讓使用者來取,也可能是實施推送,看具體需求定
* Observer:接收輸入 也就是第三方,可以有多個實現 多個一方(觀察者)
* 物件之間多對一依賴的一種設計方案,被依賴的物件為Subject,依賴的物件為Observer,Subject通知Observer變化,比如這裡的奶站是Subject,是1的一方。使用者時Observer,是多的一方
* UML類圖(案例)
* ![](https://img2020.cnblogs.com/blog/2093590/202012/2093590-20201203180955275-1727035475.png)
* 程式碼實現
* >```java
>public interface Subject {
>
> // 被觀察者介面 作為一的一方 ,需要聚合多個觀察者 可以使用List進行管理
>
> // 註冊觀察者
> void register(Observer observer);
>
> // 移除觀察者
> void remove(Observer observer);
>
> // 被觀察者狀態發生改變,進行通知所有的觀察者
> void notifyObservers();
>
>}
>
>// 實現類
>class WeatherData implements Subject {
>
> // 天氣資料類 作為被觀察者 一的一方
>
> // 溫度
> private double temperature;
> // 壓力
> private double pressure;
> // 溼度
> private double humidity;
>
> // 聚合所有的觀察者進行管理 動態進行修改 使用List集合管理觀察者們
> priv