JAVA設計模式之觀察者模式詳解

2021-08-08 22:37:12 字數 3587 閱讀 2663

場景

我們接到乙個來自氣象局的需求:氣象局需要我們構建一套系統,這系統有兩個公告牌,分別用於顯示當前的實時天氣和未來幾天的天氣預報。當氣象局發布新的天氣資料(weatherdata)後,兩個公告牌上顯示的天氣資料必須實時更新。氣象局同時要求我們保證程式擁有足夠的可擴充套件性,因為後期隨時可能要新增新的公告牌。

概況這套系統中主要包括三個部分:氣象站(獲取天氣資料的物理裝置)、weatherdata(追蹤來自氣象站的資料,並更新公告牌)、公告牌(用於展示天氣資料)

weatherdata知道如何跟氣象站聯絡,以獲得天氣資料。當天氣資料有更新時,weatherdata會更新兩個公告牌用於展示新的天氣資料。

錯誤示範

我們先來看看隔壁老王的實現:

public class weatherdata 

...}

上面這段**是典型的針對實現程式設計,這會導致我們以後增加或刪除公告牌時必須修改程式。我們現在來看看觀察者模式,然後再回來看看如何將觀察者模式應用到這個程式。

觀察者模式介紹

觀察者模式面向的需求是:a物件(觀察者)對b物件(被觀察者)的某種變化高度敏感,需要在b變化的一瞬間做出反應。舉個例子,新聞裡喜聞樂見的警察抓小偷,警察需要在小偷伸手作案的時候實施抓捕。在這個例子裡,警察是觀察者、小偷是被觀察者,警察需要時刻盯著小偷的一舉一動,才能保證不會錯過任何瞬間。程式裡的觀察者和這種真正的【觀察】略有不同,觀察者不需要時刻盯著被觀察者(例如a不需要每隔1ms就檢查一次b的狀態),二是採用註冊(_register_)或者成為訂閱(_subscribe_)的方式告訴被觀察者:我需要你的某某狀態,你要在它變化時通知我。採取這樣被動的觀察方式,既省去了反覆檢索狀態的資源消耗,也能夠得到最高的反饋速度。

觀察者模式通常基於subject和__observer__介面類來設計,下面是是類圖:

observer

觀察者模式的應用

結合上面的類圖,我們現在將觀察者模式應用到weatherdata專案中來。於是有了下面這張類圖:

observerforweatherstation

主題介面

/**

* 主題(發布者、被觀察者)

*/public inte***ce subject

觀察者介面

/**

* 觀察者

*/public inte***ce observer

公告牌用於顯示的公共介面

public inte***ce displayelement
下面我們再來看看weatherdata是如何實現的

public class weatherdata implements subject 

@override

public void registerobserver(observer observer)

@override

public void removeobserver(observer observer)

@override

public void notifyobservers()

}public void measurementschanged()

public void setmeasurements(float temperature, float humidity,

float pressure, listforecasttemperatures)

public float gettemperature()

public float gethumidity()

public float getpressure()

public listgetforecasttemperatures()

}

顯示當前天氣的公告牌currentconditionsdisplay

public class currentconditionsdisplay implements observer, displayelement 

@override

public void display()

@override

public void update()

}

顯示未來幾天天氣的公告牌forecastdisplay

public class forecastdisplay implements observer, displayelement 

@override

public void display()

}@override

public void update()

}

到這裡,我們整個氣象局的weatherdata應用就改造完成了。兩個公告牌currentconditionsdisplayforecastdisplay實現了observerdisplayelement介面,在他們的構造方法中會呼叫weatherdataregisterobserver方法將自己註冊成觀察者,這樣被觀察者weatherdata就會持有觀察者的應用,並將它們儲存到乙個集合中。當被觀察者`weatherdata狀態傳送變化時就會遍歷這個集合,迴圈呼叫觀察者公告牌更新資料的方法。後面如果我們需要增加或者刪除公告牌就只需要新增或者刪除實現了observerdisplayelement介面的公告牌就好了。

觀察者模式將觀察者和主題(被觀察者)徹底解耦,主題只知道觀察者實現了某一介面(也就是observer介面)。並不需要觀察者的具體類是誰、做了些什麼或者其他任何細節。任何時候我們都可以增加新的觀察者。因為主題唯一依賴的東西是乙個實現了observer介面的物件列表。

好了,我們測試下利用觀察者模式重構後的程式:

public class observerpatterntest 

}

輸出結果:

當前溫度為:22.0℃

當前濕度為:0.8

當前氣壓為:1.2

未來幾天的氣溫

第0天:22.0℃

第1天:-1.0℃

第2天:9.0℃

第3天:23.0℃

第4天:27.0℃

第5天:30.0℃

第6天:10.0℃

Java設計模式之觀察者模式

觀察者模式是乙個使用率非常高的模式,觀察者 observer 模式又名發布 訂閱 publish subscribe 模式,這個模式有乙個非常重要的作用就是解耦,將被觀察者和觀察者之間的依賴降到最小.像我們進場使用的adapter就使用了觀察者模式,當資料集發生變化的時候,通知adapter更新.定...

Java設計模式之觀察者模式

觀察者模式定義了一些列物件之間的一對多關係。當乙個物件改變狀態,其他依賴者都會收到通知。觀察者模式提供了一種物件設計,讓主題和觀察者之間松耦合。uml圖 觀察者介面 觀察者介面 public inte ce observer 觀察者a 觀察者a public class aimplements ob...

JAVA設計模式之觀察者模式

觀察者模式定義了一種一對多的依賴關係 簡單的解釋就是多個觀察者物件,一同觀察某個主題物件,並隨著主題物件的更新,而各自進行相應的更新 舉個例子,動物園裡飼養員是乙個主題物件,而這個飼養員所餵養的動物,就是乙個個的觀察者物件 在這個例子中的飼養員比較奇葩,他對它所餵養的動物,統一喂同一種食物,雖然動物...