23種設計模式之觀察者模式

觀察者模式的定義

定義: 定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新

通俗的說, 就是一個類的某個條件滿足時, 會調用一系列定義好的方法

其類圖如下:

23種設計模式之觀察者模式

其中的4個角色:

  1. Subject 被觀察者: 定義被觀察者必須實現的職責, 它必須能夠動態的增加、取消被觀察者. 它一般是抽象類或者實現類, 僅僅完成作為被觀察者必須實現的職責: 管理觀察者並通知觀察者
  2. Observer 觀察者: 觀察者接收到消息後, 即進行 update 操作, 對接收到的信息進行處理
  3. ConcreteSubject 具體的被觀察者: 定義被觀察者自己的業務邏輯, 同時定義對哪些事件進行通知
  4. ConcreteObserver 具體的觀察者: 每個觀察者在接收到消息後的處理反應是不同的, 每個觀察者有自己的業務邏輯

被觀察者抽象類代碼:

23種設計模式之觀察者模式

具體被觀察者代碼:

23種設計模式之觀察者模式

觀察者接口代碼:

23種設計模式之觀察者模式

具體的觀察者代碼:

23種設計模式之觀察者模式

場景類如下:

23種設計模式之觀察者模式

觀察者模式的應用

觀察者模式的優點:

  1. 觀察者和別觀察者之間是抽象耦合. 如此設計, 不管是增加觀察者還是被觀察者都非常容易擴展
  2. 建立一套觸發機制.

觀察者模式的缺點:

觀察者模式需要考慮併發效率和運行效率問題, 一個被觀察者, 多個觀察者, 開發和調試就會比較複雜, 而且在Java中消息的通知是順序執行, 一個觀察者卡殼, 會影響整體的執行效率. 在這種情況下, 一般考慮採用異步的方式

觀察者模式的使用場景:

  1. 關聯行為場景. 關聯行為是可拆分的, 而不是"組合"關係
  2. 時間多級觸發場景
  3. 跨系統的消息交換場景

觀察者模式的注意事項

1.廣播鏈的問題

一個觀察者可以有雙重身份, 既是觀察者, 也是被觀察者, 鏈一旦建立, 這個邏輯就比較複雜, 可維護性非常差. 根據經驗建議, 在一個觀察者模式中最多出現一個對象既是觀察者也是被觀察者, 也就是說消息最多轉發一次, 這還是比較好控制的.

觀察者模式和責任鏈模式的最大區別就是觀察者廣播鏈在傳播的過程中消息是隨時更改的, 它是由相鄰的兩個節點協商的消息結構; 而責任鏈模式在消息傳遞過程中基本上保持消息不可變, 如果要改變,也只是在 原有的消息上進行修正

2.異步處理問題

被觀察者發生動作了, 觀察者要做出回應, 如果觀察者比較多, 而且處理時間比較長怎麼辦, 用異步唄, 異步處理就要考慮線程安全和隊列的問題

觀察者模式的擴展

1.Java 世界中的觀察者模式

在Java中, java.util.Observable 實現了被觀察者的功能, 被觀察者直接繼承即可, java.util.Observer 是觀察者接口, 已經寫好了

2.項目中真實的觀察者模式

  1. 觀察者和被觀察者之間的消息溝通. 被觀察者狀態改變會觸發觀察者的一個行為, 同時會傳遞一個消息給觀察者, 在實際中一般的做法是: 觀察者中的update方法接受兩個參數, 一個是被觀察者, 一個是DTO(Data Transfer Object, 數據傳輸對象), DTO一般是一個純潔的JavaBean, 由被觀察者生成, 當然, 如果考慮到遠程傳輸, 一般消息是XML格式傳遞
  2. 觀察者響應方式. 如果觀察者來不及相應, 被觀察者的時間就會被拉長. 觀察者如何快速響應呢? 有兩個辦法: 一是採用多線程技術, 也就是通常說的異步架構; 二是緩存技術.
  3. 被觀察者儘量自己做主. 在設計的時候要考慮靈活性,否則會加重觀察者的業務邏輯, 一般是這樣做的, 對被觀察者的業務邏輯 doSomething 方法實現重載, 如增加一個 doSomething(boolean isNotifyObs) 方法, 決定是否通知觀察者, 而不是在消息到達觀察者時才判斷是否要消費

觀察者模式在實際項目和生活中的例子:

  1. 文件系統. 比如, 在一個目錄下新建立一個文件, 這個動作會同時通知目錄管理器增加該目錄, 並通知磁盤管理器減少1Kb的空間, 這裡 "文件" 是一個被觀察者, "目錄管理器"和"磁盤管理器"則是觀察者
  2. 貓鼠遊戲. 夜裡貓叫一聲,家裡老鼠撒腿就跑, 同時也吵醒了熟睡的主人, 這裡"貓"就是被觀察者, 老鼠和人則是觀察者
  3. ATM取錢. 在ATM機器上取錢,多次輸錯密碼, 卡被ATM吞掉, 吞卡動作發生時, 會觸發哪些事件呢?第一, 攝像頭連續快拍, 第二, 通知監控系統,吞卡發生, 第三, 初始化ATM機屏幕, 返回最初狀態. 一般前兩個動作都是通過觀察者模式完成的, 最後一個動作是異常來完成的
  4. 廣播收音機. 電臺在廣播, 可以打開一個收音機聽, 也可以打開兩個收音機來收聽, 電臺就是被觀察者, 收音機就是觀察者


分享到:


相關文章: