觀察者模式又叫做釋出-訂閱(publish/subscribe)模式。
觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
特點:
觀察者模式的通知者可以有任意數目的依賴它的observer,一旦通知者的狀态改變,所有的observer都可以得到通知。通知者發出通知時并不需要知道誰是它的觀察者,也就是說,具體觀察者是誰,它根本不需要知道。
總得來講,觀察者模式所做的工作其實就是在接觸耦合。讓耦合的雙方都依賴于抽象,而不是依賴于具體。進而使得各自的變化都不會影響另一邊的變化。
那麼在觀察者模式時,如果觀察者之間非常相似,那麼可以用抽象類來共用一些代碼,但是現實程式設計中,具體的觀察者完全有可能是風馬牛不相及的類,但它們都需要根據通知者的通知來做出update()操作,是以讓它們都實作下面一個接口就可以實作這個想法了。
下面這個觀察者模式,我會一步步以例子進行分析。
下面的觀察者以工作中開小差玩遊戲的同僚為原型,通知者以秘書為原型,一旦老闆出現,秘書立即通知玩遊戲、睡覺的同僚,做好準備。
<a></a>
結果輸出為:
上面的類雖然能實作功能,但是仔細一看,他們之間的耦合太大了。秘書類需要增加觀察者,而觀察者們需要秘書類。如果觀察者不止一個人,并且幹得事情不一樣的時候(比如睡覺、吃東西什麼的),就無法讓秘書增加對應的觀察者,并一起通知。我們來改改代碼。
抽象觀察者類(observer)
抽象通知者類(notification)
觀察者們
通知者們
進行測試:
比如我們在使用eclipse以及xcode等一些編輯工具的時候,我們可能一個運作可以導緻很多視窗隐藏或者出現,而且各個變化都涉及到不同的控件。那麼我們要是想通知它們,不可能讓它們都去實作observer接口,因為這些控件早都已經被他們的制造商給封裝了。
盡管我們用了依賴倒轉原則,但是‘抽象通知者’還是依賴‘抽象觀察者’,也就是說,萬一沒有了抽象觀察者這樣的接口,我這通知的功能就完不成了。另外就是每個具體觀察者,它不一定要使用‘更新’這個方法,有可能是‘工具箱隐藏’方法,有可能是‘導航欄變色’等。這根本就是不同名的方法,這應該就是不足的地方吧。
委托就是一種引用方法的類型。一旦為委托配置設定了方法,委托将與該方法具有完全相同的行為。委托方法的使用可以像其他任何方法一樣,具有參數和傳回值。委托可以看做是對函數的抽象,是函數的“類”,委托的執行個體将代表一個具體的函數。
一個委托可以搭載多個方法,所有方法被依次喚起。更重要的是,它可以使得委托對象所搭載的方法并不需要屬于同一個類。
剛剛的例子我們加上event和eventhandler作為委托,修改代碼如下:
最後總結:
1、通知者不知道玩遊戲的和睡覺的存在,完全解耦。(功勞歸功于event和eventhandler)
2、老闆來後,一次通知,并且通知的消息可以變化,執行不同的方法
3、擴充性很高,再來一個玩紙牌的加上就可以,告訴一下通知者。