前言
觀察者模式是屬于設計模式中的行為型模式,所謂<code>行為型</code>就是指對象的動作發生改變,比如方法以及狀态。那麼觀察者模式是一種什麼模式呢?說白了,觀察者模式解決的一對多的依賴關系,當一個對象的狀态發生改變的時候,其他依賴此對象的對象會得到通知并且做出相應的改變。但從定義上還是很難了解。我們可以從一個簡單的例子中更深地去體會觀察者模式。
某公司的兩名職員在主管離開辦公室後,一個在看股票,一個在玩遊戲。公司有一個前台,該兩名職員讓前台當主管回來的時候通知他們不讓主管看到他們在幹其他的事。
根據上述場景,下面是我寫出的第一版代碼:
最後程式的運作結果如下:
我在程式使用的都是抽象類,抽象類是對類的抽象,類是對對象抽象。但是如果考慮到通知者有可能是完全不相關的對象,使用抽象類就不是很合理了,于是可以換成接口,接口是對類行為的抽象,通知者的核心職責就是告訴觀察者具體的通知,其他的都不是最重要的。下面對代碼進行進一步的的優化:
最後的測試結果是:
從以上兩個測試結果可以發現,隻要notifyer的message屬性發生改變,其所管轄的觀察者的動作也發生了更新。注意到在測試代碼中沒有将第三個對象添加進來,這樣當notifyer的狀态發生改變其動作不會發生更新。這樣隻有前兩個對象發生了動作的更新。也就是說notifyer這個對象的狀态發生改變導緻了其他兩個對象的改變。而觀察者模式也正是在這種情況下使用的。當一個對象的狀态改變導緻其他對象的狀态也發生改變,而且不知道有多少具體的對象的狀态要發生改變的時候,應該使用觀察者模式。觀察者模式有兩個關鍵對象subject(對應上面代碼中的notifyer和inotify對象)和observer(對應上面的employee對象)。subject狀态的改變會導緻observer對象的狀态的改變一個subject對象可以吧狀态的改變通知給任意數目的觀察者對象。一個subject不需要知道具體的觀察者,一個觀察者也不需要知道其他觀察者是否存在。實際上觀察者模式主要是為了解耦(實際上23種設計模式中都展現了這一點,隻不過不同的設計模式展現程度不同罷了),使得對象之間不依賴具體而是依賴抽象。這樣設計的好處對具體的大修改不會影響其他依賴抽象的類,使得類之間的耦合度降低。
可以發現,在上面我們的代碼中,具體的subject是依賴observer對象的,這樣的依賴會不會影響呢?答案是肯定的。
雖然subject和observer都是抽象的,但是難保在系統中會一直存在這樣抽象的observer,是以這樣的依賴已經最大程度減少了程式之間的耦合,但在這種情況下還是存在問題的。那麼還沒有其他的方法解決這種耦合呢?有。我們可以采用一種委托的事件機制完成進一步的解耦。事件委托可以将委托者的方法可以事件中去執行,事件委托僅僅需要的是要執行方法的對象、方法以及參數清單,這樣事件委托對象就可以根據這三個參數執行制定對象的指定方法,從直覺上了解,有點象代理,但不同于代理,由于在java中沒有現成的事件委托模型可以使用,可以實作一個自己的事件委托處理器。實作之後,我們在subject中引入這個事件委托處理器,并添加相應的事件響應方法,而observer對象不需要做任何改變。具體事件委托處理器的代碼可以參考我的github上的源碼。
最後對觀察者模式做一個簡單的總結:
觀察者模式主要适用于一個對象的改變會導緻其他對象狀态的改變的情況
使用抽象降低需要關聯對象的耦合,不依賴具體而是依賴抽象
觀察者模式的不足在于如果observer對象的不再存在将對系統産生重大影響