觀察者模式

2022-12-03 15:01:05

沒人疼就去健身,練完渾身疼。

讓你的物件,知悉狀況

自定義實現觀察者模式

Internet氣象觀測站

應用就是利用WeatherData物件取得感測器資料,並更新三個佈告板:目前狀況、氣象統計和天氣預報。

WeatherData

先看一個錯誤示範

public class WeatherData {
// 範例變數宣告

public void measurementsChanged() {
// 取得測量值
float temp = getTemperature();
float humidty = getHumidity();
float pressure = getpRESSURE();

// 呼叫每個佈告板更新顯示,傳入最新的測量
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecasDisplay.update(temp, humidity, pressure);
}

// 其它方法
}

這樣做有什麼不對

  1. 違反設計原則,最好是把不變的部分和會改變的東西分別封裝起來。

// 呼叫每個佈告板更新顯示,傳入最新的測量
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecasDisplay.update(temp, humidity, pressure);

這部分可能會改變的東西,可以提出來單獨封裝。

  1. 針對介面程式設計,而不是針對實現程式設計,上面的update()引數都是溫度、溼度、氣壓,看起來像是一個統一的介面。這樣針對具體的實現程式設計,會導致我們以後在增加或刪除佈告板時必須修改程式。

出版者 + 訂閱者 = 觀察者模式

定義觀察者模式

觀察者模式定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。

結構類圖

鬆耦合的威力

關於觀察者的一切,主題只知道觀察者實現了某個介面(也就是Observer介面)。主題不需要知道觀察者具體類是誰,做了些什麼或其它任何細節。改變主題或觀察者其中一方,並不會影響另一方。因為兩者是鬆耦合的,只要他們之間的介面仍被遵守,我們就可以自由地改變他們。

設計原則:

為了互動物件之間的鬆耦合設計而努力。

鬆耦合的設計之所以能讓我們建立有彈性的OO系統,能夠應對變化,是因為物件之間的互相依賴降到了最低。

設計氣象站

使用Java內建的封裝類實現觀察者模式

除了自定義介面實現觀察者模式,還可以藉助Java已經封裝好的工具類來實現。

  • 優點:使用上更加方便,甚至可以使用推(push)或拉(pull)的方式傳送資料。

  • 缺點:內建的觀察者不是一個介面,而是一個類,你要使用的時候只能使用繼承,但是java不支援多重繼承,你要實現其他類的話,就會陷入矛盾。(而且內建的這套實現已經被官方標記棄用了,所以最好還是使用自定義介面的方式實現,更方便且更有彈性)

tips:

這裡面使用了一個setChanged()方法用來標記狀態已經改變的事實。有什麼用呢?

使得程式碼更加有彈性,比方說,如果沒有setChanged()方法,氣象站的測量非常精確,每次溫度值有十分之一度就開始更新資料,現在我希望半度以上才更新資料,就可以在溫度到達半度時呼叫setChanged()方法,進行有效的數值更新。

總結

觀察者模式——在物件之間定義一對多的依賴,這樣一來,當一個物件改變狀態依賴它的物件就會收到通知,並自動更新。

程式碼地址:

https://gitee.com/LHDAXIE/design-mode