前言
????在現實生活中,如果我們想知道某個領域的最新消息,我們可能會訂閱很多相關的信息源,比如報紙、微博、公眾號、廣播、電視等等。任何人都可以在任何時候查閱而不會打擾其他人。我們把這一思想引入面向對象軟件設計中來,用以消除具有不同行為的對象之間的耦合。通過這一模式,不同對象可以協同工作,同時它們也可以被復用于其它地址。我們稱之為觀察者模式。
什么是觀察者模式
????觀察者模式也叫做發布-訂閱模式。如它的別名暗示一樣,它很像雜志的訂閱。當從雜志發布商訂閱雜志時,讀者把名字和郵寄地址提供給發行商,這樣新的一期就能送到讀者手上。這正是觀察者模式的工作方式。觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。
????Observer
從 Subject
訂閱通知。 ConcreteObserver
實現抽象并重載 update
方法。一旦 Subject
的實例需要通知 Observer
任何新的變更, Subject
會通過 notify
方法發送 Update
消息來通知存儲在內部列表中所有注冊的 Observer
,在 ConcreteObserver
的 update
方法的實現中, Subject
的內部狀態可以被取得并在以后進行處理。
什么時候使用觀察者模式
- 有兩種抽象類型相互依賴。將它們封裝在各自的對象中,就可以對它們單獨進行改變和復用。
- 對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變。
- 一個對象必須通知其它對象,而它又不需要知道其它對象是什么。
- 需要在系統中創建一個觸發鏈,A對象的行為將影響B對象,B對象的行為將影響C對象……,可以使用觀察者模式創建一種鏈式觸發機制。
觀察者模式的優缺點
觀察者模式的優點
- 觀察者和被觀察者是抽象耦合的。
- 建立一套觸發機制。
觀察者模式的缺點
- 如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
- 如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。
- 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎么發生變化的,而僅僅只是知道觀察目標發生了變化。
Cocoa 中的觀察者模式
NSNotification
???? Cocoa 的通知機制基于觀察者模式實現了消息的一對多廣播。程序中的對象將自己或其他對象添加到列表中一個或多個通知的觀察者,每個通知都由一個全局字符串(通知名稱)標識。想要通知其他對象的對象——被觀察對象——創建一個通知對象并將其發布到通知中心。通知中心確定特定通知的觀察者,并通過消息將通知發送給他們。通知消息調用的方法必須符合某個單參數簽名。該方法的參數是通知對象,其中包含通知名稱、觀察對象和包含任何補充信息的字典。
???? 發布通知是一個同步過程。在通知中心向所有觀察者廣播通知之前,發布對象不會重新獲得控制權。對于異步行為,可以將通知放入通知隊列;控制立即返回到發布對象,通知中心在到達隊列頂部時廣播通知。
???? 常規通知(即通知中心廣播的通知)僅在進程內。如果要向其他進程廣播通知,可以使用分布式通知中心及其相關API。
通知類是
NSNotification
(用于通知對象)、NSNotificationCenter
(發布通知和添加觀察者)、NSNotificationQueue
(將通知入隊)
Key-Value Observer
???? 鍵值觀察是一種機制,它允許對象在其他對象的特定屬性發生更改時得到通知。它基于 <NSKeyValueObserving>
非正式協議。觀察到的屬性可以是簡單的屬性、一對一關系或一對多關系。在模型-視圖-控制器模式的上下文中,鍵值觀察尤其重要,因為它使視圖對象能夠通過控制器層觀察模型對象的變化。因此,它是 Cocoa 的重要組成部分綁定技術。
????Cocoa 提供了許多方法的默認“自動”實現 <NSKeyValueObserving>
協議,為所有符合要求的對象提供了屬性觀察能力。
關于 Key-Value Observer 可以移步 了解 Key-Value Observing
通知與鍵-值 觀察之間的主要差別
通知 | 鍵-值觀察 |
---|---|
一個中心對象為所有觀察者提供變更通知 | 被觀察的對象直接向觀察者發送通知 |
廣義上關注程序事件 | 綁定于特定對象屬性的值 |
總結
????當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。關于觀察者模式,Cocoa 框架為我們提供了兩種實現好的觀察者模式: NSNotification 和 Key-Value Observer。