designPattern

Design Pattern(2) - Observer

以下文章是閱讀 深入淺出Design Pattern 還有 聖經還有Source making的筆記 圖片截圖自lynda.com的Foundations of Programming: Design Patterns 要更深入的理解一定要去看這兩本書

目的

定義一對多的依存關係 當物件狀態一有變動 就自動通知相依物件做該做的更新動作

現實生活的例子就像是你訂報紙 當有新報紙出來的時候就會送給所有有訂閱的人一份

書上的例子是有一個中央氣象局會有許多天氣的資料 有三個不同的氣象顯示器(目前狀況, 統計資料, 天氣預報)跟中央氣象局subscribe資料 只要中央氣象局有更新 就會通知所有的氣象顯示器

如果你寫程式用過framework, Observer就是MVC裡面的View

結構

Alt text

優點

  1. 可以讓你單獨改變Subject或Observer 不會影響對方

  2. Subject不關心有多少用戶 他唯一要做的事就是跟observer說一聲哈囉我的狀態變化囉 至於observer要做什麼事不關我的事 observer可以變化可以不變化

缺點

  1. 改變一個subject可能造成的後果Subject並不知道 比如說某個state的值overflow了 某些observer可能有處理這種case 有些可能沒有 code會不好maintain

  2. 如果只是單純的跟observer說 哈囉我變囉 Observer需要花費時間精力自行推理是什麼東西變了

實作細節

1.通常一個observer不會只訂閱一個subject 它通常會一次訂閱好幾個 所以update這個function必須更general一點 比如把subject當作argument傳給update

2.如果一個subject要被刪除了 他必須告訴所有的observer說 安安別等我囉 這樣observer那邊可以把subject的reference刪掉

3.實作上 你可以選擇讓subject廣播多一點資訊或是少一點資訊 最極端的就是兩種模式 push跟pull

push就是不管這個observer感不感興趣 我都把所有資料給你 你拿你需要的資料 更新你自己

pull就是我只跟所有observer說我改了 你需要什麼資料 自己來看我改了什麼

4.根據第三點的延伸 其實可以extend subject的interface 讓不同observer只登記他感興趣的更新(比如說中央氣象台有三個update: updateTemperature, updateHumidity 跟updatePressure)

5.封裝複雜的更新: 比如說某個事件發生了 他會更新多個subject 如果每個subject都call update, 那同時訂閱這多個subject的observer就會被叫很多次 很不方便

所以當有改變的時候 先把所有要notify的observer記錄起來 所有subject的所有observer都記起來後再一次notify

DP rule#4 盡量讓需要互動的物件之間關係鬆綁(loosely coupled)

loosely coupled意思是說兩者之間可以互動 但並不需要知道太多彼此的細節

在這個case裡 以Subject來說 Subject只知道所有的observer實作了Observer介面 我連你是什麼class都不需要知道 更不用說實作細節

以Observer來說 任何時候都可以新增observer(包括run-time) 而且有新的observer出現時 subject完全不用更動 只要subject好好maintain observer lists

loose coupling 讓物件跟物件的依賴關係最小化 我們就可以建造更有彈性(容易應付變化)的系統