觀察者模式:
定義對象是一種一對多的關系,當一這方的狀態發生變化時,多的之方需要得到通知或更新.
觀察者模式包含以下幾個部份:
a.主題接口, 此接口是定義一之方的功能,此接口至少應該包含兩個方法:
1.添加觀察者
2.通知觀察者
b.主題接口實現類
c.觀察者接口,此接口定義多方的功能,至少應該包含以下功能
d.觀察者實現類
觀察者模式的UML圖:
觀察者與后繼動作
對于觀察者而言,除了監視被觀察對象之外,更重要的是當發現被觀察對象發生改變時應該采取什么樣的動作,比如在學校教務系統中,HeadMaster一旦注意到有新的學生信息被保存成功時,就會調用sendMail方法發送一封郵件到校長的郵箱中,我們把諸如此類的動作稱為后繼動作。對于觀察者而言,其后繼動作可以分為兩類:基于“推數據”的后繼動作和基于“拉數據”的后繼動作。
A.推數據
所謂“推數據”,即當被觀察對象發生變化時,它將把相關的變化數據以參數的形式傳給被觀察者。比如,在學校教務系統的觀察者模式中,我們使用的就是基于“推數據”的后繼動作。當StudentBean的當前對象被保存到數據庫后,該對象將作為參數被傳入到update方法中,作為觀察者的HeadMaster將從update方法的參數中得到需要的數據,形象一點來說,數據是由被觀察者“推”給觀察者的。
基于“推數據”的后繼動作的優點在于觀察者一方無需考慮數據是如何得到的,只需對得到的數據進行相應的處理即可。此時,觀察者與被觀察者之間幾乎沒有什么耦合。
基于“推數據”的后繼動作的缺點在于觀察者獲得數據的形式是被動的,對于同一個觀察對象而言,不同觀察者想要獲得的數據很有可能是不同的,但此時他們將不得不接受由參數傳入的一些與自己沒有關系的數據。比如,在學校教務系統中,校長可能只想得到學生的學歷信息,而教務主任只想得到學生的交費信息,但他們將不得不接受一些與己無關的額外信息。此外,若方法update的參數發生變化也會對不同觀察者的后繼動作造成一些影響。
B.拉數據
所謂“拉數據”,即當被觀察對象發生變化時,不是由被觀察者把數據傳給觀察者,而是由觀察者主動到被觀察對象中來取得數據。形象一點來說,數據是由觀察者主動到被觀察者中來“拉” 的。當然,此時在被觀察的對象或接口中需要提供一些方法來供觀察者“拉”,同時在觀察者對象中也需提供一個對被觀察對象的引用的屬性,由此也造成了觀察者與被觀察者之間一定程度的耦合。
觀察者模式的效果有以下幾個優點:
(1)觀察者模式在被觀察者和觀察者之間建立一個抽象的耦合。被觀察者角色所知道的只是一個具體現察者聚集,每一個具體現察者都符合一個抽象觀察者的接口。被觀察者并不認識任何一個具體觀察者,它只知道它們都有一個共同的接口。由于被觀察者和觀察者沒有緊密地耦合在一起,因此它們可以屬于不同的抽象化層次。
(2)觀察者模式支持廣播通信。被觀察者會向所有的登記過的觀察者發出通知。
觀察者模式有下面的一些缺點:
(1)如果一個被觀察者對象有很多直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
(2)如果在被觀察者之間有循環依賴的話,被觀察者會觸發它們之間進行循環調用,導致系統崩潰。在使用觀察考模式時要特別注意這一點。
(3)如果對觀察者的通知是通過另外的線程進行異步投遞的話,系統必須保證投遞是以自恰的方式進行的。
(4)雖然觀察者模式可以隨時使觀察者知道所觀察的對象發生了變化,但是觀察者模式沒有相應的機制使觀察者知道所觀察的對象是怎么發生變化的。