前言
????在現(xiàn)實(shí)生活中,如果我們想知道某個(gè)領(lǐng)域的最新消息俺陋,我們可能會(huì)訂閱很多相關(guān)的信息源豁延,比如報(bào)紙、微博腊状、公眾號(hào)诱咏、廣播、電視等等缴挖。任何人都可以在任何時(shí)候查閱而不會(huì)打擾其他人袋狞。我們把這一思想引入面向?qū)ο筌浖O(shè)計(jì)中來(lái),用以消除具有不同行為的對(duì)象之間的耦合映屋。通過(guò)這一模式苟鸯,不同對(duì)象可以協(xié)同工作,同時(shí)它們也可以被復(fù)用于其它地址棚点。我們稱(chēng)之為觀察者模式早处。
什么是觀察者模式
????觀察者模式也叫做發(fā)布-訂閱模式。如它的別名暗示一樣瘫析,它很像雜志的訂閱砌梆。當(dāng)從雜志發(fā)布商訂閱雜志時(shí),讀者把名字和郵寄地址提供給發(fā)行商颁股,這樣新的一期就能送到讀者手上么库。這正是觀察者模式的工作方式。觀察者模式定義對(duì)象間的一種一對(duì)多的依賴(lài)關(guān)系甘有,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí)诉儒,所有依賴(lài)于它的對(duì)象都得到通知并被自動(dòng)更新。
????Observer
從 Subject
訂閱通知亏掀。 ConcreteObserver
實(shí)現(xiàn)抽象并重載 update
方法忱反。一旦 Subject
的實(shí)例需要通知 Observer
任何新的變更泛释, Subject
會(huì)通過(guò) notify
方法發(fā)送 Update
消息來(lái)通知存儲(chǔ)在內(nèi)部列表中所有注冊(cè)的 Observer
,在 ConcreteObserver
的 update
方法的實(shí)現(xiàn)中温算, Subject
的內(nèi)部狀態(tài)可以被取得并在以后進(jìn)行處理怜校。
什么時(shí)候使用觀察者模式
- 有兩種抽象類(lèi)型相互依賴(lài)。將它們封裝在各自的對(duì)象中注竿,就可以對(duì)它們單獨(dú)進(jìn)行改變和復(fù)用茄茁。
- 對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象,而不知道具體有多少對(duì)象有待改變巩割。
- 一個(gè)對(duì)象必須通知其它對(duì)象裙顽,而它又不需要知道其它對(duì)象是什么。
- 需要在系統(tǒng)中創(chuàng)建一個(gè)觸發(fā)鏈宣谈,A對(duì)象的行為將影響B(tài)對(duì)象愈犹,B對(duì)象的行為將影響C對(duì)象……,可以使用觀察者模式創(chuàng)建一種鏈?zhǔn)接|發(fā)機(jī)制闻丑。
觀察者模式的優(yōu)缺點(diǎn)
觀察者模式的優(yōu)點(diǎn)
- 觀察者和被觀察者是抽象耦合的漩怎。
- 建立一套觸發(fā)機(jī)制。
觀察者模式的缺點(diǎn)
- 如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話嗦嗡,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間勋锤。
- 如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴(lài)的話,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用酸钦,可能導(dǎo)致系統(tǒng)崩潰怪得。
- 觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的,而僅僅只是知道觀察目標(biāo)發(fā)生了變化卑硫。
Cocoa 中的觀察者模式
NSNotification
???? Cocoa 的通知機(jī)制基于觀察者模式實(shí)現(xiàn)了消息的一對(duì)多廣播。程序中的對(duì)象將自己或其他對(duì)象添加到列表中一個(gè)或多個(gè)通知的觀察者蚕断,每個(gè)通知都由一個(gè)全局字符串(通知名稱(chēng))標(biāo)識(shí)欢伏。想要通知其他對(duì)象的對(duì)象——被觀察對(duì)象——?jiǎng)?chuàng)建一個(gè)通知對(duì)象并將其發(fā)布到通知中心。通知中心確定特定通知的觀察者亿乳,并通過(guò)消息將通知發(fā)送給他們硝拧。通知消息調(diào)用的方法必須符合某個(gè)單參數(shù)簽名。該方法的參數(shù)是通知對(duì)象葛假,其中包含通知名稱(chēng)障陶、觀察對(duì)象和包含任何補(bǔ)充信息的字典。
???? 發(fā)布通知是一個(gè)同步過(guò)程聊训。在通知中心向所有觀察者廣播通知之前抱究,發(fā)布對(duì)象不會(huì)重新獲得控制權(quán)。對(duì)于異步行為带斑,可以將通知放入通知隊(duì)列鼓寺;控制立即返回到發(fā)布對(duì)象勋拟,通知中心在到達(dá)隊(duì)列頂部時(shí)廣播通知。
???? 常規(guī)通知(即通知中心廣播的通知)僅在進(jìn)程內(nèi)妈候。如果要向其他進(jìn)程廣播通知敢靡,可以使用分布式通知中心及其相關(guān)API。
通知類(lèi)是
NSNotification
(用于通知對(duì)象)苦银、NSNotificationCenter
(發(fā)布通知和添加觀察者)啸胧、NSNotificationQueue
(將通知入隊(duì))
Key-Value Observer
???? 鍵值觀察是一種機(jī)制,它允許對(duì)象在其他對(duì)象的特定屬性發(fā)生更改時(shí)得到通知幔虏。它基于 <NSKeyValueObserving>
非正式協(xié)議纺念。觀察到的屬性可以是簡(jiǎn)單的屬性、一對(duì)一關(guān)系或一對(duì)多關(guān)系所计。在模型-視圖-控制器模式的上下文中柠辞,鍵值觀察尤其重要,因?yàn)樗挂晥D對(duì)象能夠通過(guò)控制器層觀察模型對(duì)象的變化主胧。因此叭首,它是 Cocoa 的重要組成部分綁定技術(shù)。
????Cocoa 提供了許多方法的默認(rèn)“自動(dòng)”實(shí)現(xiàn) <NSKeyValueObserving>
協(xié)議踪栋,為所有符合要求的對(duì)象提供了屬性觀察能力焙格。
關(guān)于 Key-Value Observer 可以移步 了解 Key-Value Observing
通知與鍵-值 觀察之間的主要差別
通知 | 鍵-值觀察 |
---|---|
一個(gè)中心對(duì)象為所有觀察者提供變更通知 | 被觀察的對(duì)象直接向觀察者發(fā)送通知 |
廣義上關(guān)注程序事件 | 綁定于特定對(duì)象屬性的值 |
總結(jié)
????當(dāng)對(duì)象間存在一對(duì)多關(guān)系時(shí),則使用觀察者模式(Observer Pattern)夷都。關(guān)于觀察者模式眷唉,Cocoa 框架為我們提供了兩種實(shí)現(xiàn)好的觀察者模式: NSNotification 和 Key-Value Observer。