天天看點

設計模式-觀察者模式

觀察者模式又叫做釋出-訂閱(publish/subscribe)模式。

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。

特點:

觀察者模式的通知者可以有任意數目的依賴它的observer,一旦通知者的狀态改變,所有的observer都可以得到通知。通知者發出通知時并不需要知道誰是它的觀察者,也就是說,具體觀察者是誰,它根本不需要知道。

總得來講,觀察者模式所做的工作其實就是在接觸耦合。讓耦合的雙方都依賴于抽象,而不是依賴于具體。進而使得各自的變化都不會影響另一邊的變化。

那麼在觀察者模式時,如果觀察者之間非常相似,那麼可以用抽象類來共用一些代碼,但是現實程式設計中,具體的觀察者完全有可能是風馬牛不相及的類,但它們都需要根據通知者的通知來做出update()操作,是以讓它們都實作下面一個接口就可以實作這個想法了。

下面這個觀察者模式,我會一步步以例子進行分析。

下面的觀察者以工作中開小差玩遊戲的同僚為原型,通知者以秘書為原型,一旦老闆出現,秘書立即通知玩遊戲、睡覺的同僚,做好準備。

<a></a>

結果輸出為:

上面的類雖然能實作功能,但是仔細一看,他們之間的耦合太大了。秘書類需要增加觀察者,而觀察者們需要秘書類。如果觀察者不止一個人,并且幹得事情不一樣的時候(比如睡覺、吃東西什麼的),就無法讓秘書增加對應的觀察者,并一起通知。我們來改改代碼。

抽象觀察者類(observer)

抽象通知者類(notification)

觀察者們

通知者們

進行測試:

比如我們在使用eclipse以及xcode等一些編輯工具的時候,我們可能一個運作可以導緻很多視窗隐藏或者出現,而且各個變化都涉及到不同的控件。那麼我們要是想通知它們,不可能讓它們都去實作observer接口,因為這些控件早都已經被他們的制造商給封裝了。

盡管我們用了依賴倒轉原則,但是‘抽象通知者’還是依賴‘抽象觀察者’,也就是說,萬一沒有了抽象觀察者這樣的接口,我這通知的功能就完不成了。另外就是每個具體觀察者,它不一定要使用‘更新’這個方法,有可能是‘工具箱隐藏’方法,有可能是‘導航欄變色’等。這根本就是不同名的方法,這應該就是不足的地方吧。

委托就是一種引用方法的類型。一旦為委托配置設定了方法,委托将與該方法具有完全相同的行為。委托方法的使用可以像其他任何方法一樣,具有參數和傳回值。委托可以看做是對函數的抽象,是函數的“類”,委托的執行個體将代表一個具體的函數。

一個委托可以搭載多個方法,所有方法被依次喚起。更重要的是,它可以使得委托對象所搭載的方法并不需要屬于同一個類。

剛剛的例子我們加上event和eventhandler作為委托,修改代碼如下:

最後總結:

1、通知者不知道玩遊戲的和睡覺的存在,完全解耦。(功勞歸功于event和eventhandler)

2、老闆來後,一次通知,并且通知的消息可以變化,執行不同的方法

3、擴充性很高,再來一個玩紙牌的加上就可以,告訴一下通知者。

繼續閱讀