1. 程式人生 > >17.java設計模式之觀察者模式

17.java設計模式之觀察者模式

#### 基本需求: * 氣象站可以將每天測量到的溫度,溼度,氣壓等等,以公告的形式釋出出去(比如釋出到自己的網站或第三方) * 需要設計開放型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