摘要:或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱(chēng),但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。參考文章訂閱發(fā)布模式和觀察者模式真的不一樣
首選我們需要先了解兩者的定義和實(shí)現(xiàn)的方式,才能更好的區(qū)分兩者的不同點(diǎn)。
或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱(chēng),但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。
訂閱發(fā)布模式在軟件架構(gòu)中,發(fā)布-訂閱是一種消息范式,消息的發(fā)送者(稱(chēng)為發(fā)布者)不會(huì)將消息直接發(fā)送給特定的接收者(稱(chēng)為訂閱者)。而是將發(fā)布的消息分為不同的類(lèi)別,無(wú)需了解哪些訂閱者(如果有的話)可能存在。同樣的,訂閱者可以表達(dá)對(duì)一個(gè)或多個(gè)類(lèi)別的興趣,只接收感興趣的消息,無(wú)需了解哪些發(fā)布者(如果有的話)存在。
或許你用過(guò) eventemitter、node 的 events、Backbone 的 events 等等,這些都是前端早期,比較流行的數(shù)據(jù)流通信方式,即訂閱發(fā)布模式。
從字面意思來(lái)看,我們需要首先訂閱,發(fā)布者發(fā)布消息后才會(huì)收到發(fā)布的消息。不過(guò)我們還需要一個(gè)中間者來(lái)協(xié)調(diào),從事件角度來(lái)說(shuō),這個(gè)中間者就是事件中心,協(xié)調(diào)發(fā)布者和訂閱者直接的消息通信。
完成訂閱發(fā)布整個(gè)流程需要三個(gè)角色:
發(fā)布者
事件中心
訂閱者
以事件為例,簡(jiǎn)單流程如下:
發(fā)布者->事件中心<=>訂閱者,訂閱者需要向事件中心訂閱指定的事件 -> 發(fā)布者向事件中心發(fā)布指定事件內(nèi)容 -> 事件中心通知訂閱者 -> 訂閱者收到消息(可能是多個(gè)訂閱者),到此完成了一次訂閱發(fā)布的流程。
簡(jiǎn)單的代碼實(shí)現(xiàn)如下:
class Event { constructor() { // 所有 eventType 監(jiān)聽(tīng)器回調(diào)函數(shù)(數(shù)組) this.listeners = {} } /** * 訂閱事件 * @param {String} eventType 事件類(lèi)型 * @param {Function} listener 訂閱后發(fā)布動(dòng)作觸發(fā)的回調(diào)函數(shù),參數(shù)為發(fā)布的數(shù)據(jù) */ on(eventType, listener) { if (!this.listeners[eventType]) { this.listeners[eventType] = [] } this.listeners[eventType].push(listener) } /** * 發(fā)布事件 * @param {String} eventType 事件類(lèi)型 * @param {Any} data 發(fā)布的內(nèi)容 */ emit(eventType, data) { const callbacks = this.listeners[eventType] if (callbacks) { callbacks.forEach((c) => { c(data) }) } } } const event = new Event() event.on("open", (data) => { console.log(data) }) event.emit("open", { open: true })
Event 可以理解為事件中心,提供了訂閱和發(fā)布功能。
訂閱者在訂閱事件的時(shí)候,只關(guān)注事件本身,而不關(guān)心誰(shuí)會(huì)發(fā)布這個(gè)事件;發(fā)布者在發(fā)布事件的時(shí)候,只關(guān)注事件本身,而不關(guān)心誰(shuí)訂閱了這個(gè)事件。
觀察者模式觀察者模式定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)目標(biāo)對(duì)象,當(dāng)這個(gè)目標(biāo)對(duì)象的狀態(tài)發(fā)生變化時(shí),會(huì)通知所有觀察者對(duì)象,使它們能夠自動(dòng)更新。
觀察者模式我們可能比較熟悉的場(chǎng)景就是響應(yīng)式數(shù)據(jù),如 Vue 的響應(yīng)式、Mbox 的響應(yīng)式。
觀察者模式有完成整個(gè)流程需要兩個(gè)角色:
目標(biāo)
觀察者
簡(jiǎn)單流程如下:
目標(biāo)<=>觀察者,觀察者觀察目標(biāo)(監(jiān)聽(tīng)目標(biāo))-> 目標(biāo)發(fā)生變化-> 目標(biāo)主動(dòng)通知觀察者。
簡(jiǎn)單的代碼實(shí)現(xiàn)如下:
/** * 觀察監(jiān)聽(tīng)一個(gè)對(duì)象的變化 * @param {Object} subject 觀察的目標(biāo) * @param {Function} callback 目標(biāo)變化觸發(fā)的回調(diào) */ function observer(subject, callback) { Object.defineProperty(subject, "description", { get() { return this.data.description }, set(val) { this.data.description = val // 目標(biāo)主動(dòng)通知觀察者 callback && callback(val) }, }) }
可運(yùn)行例子如下:
兩者的區(qū)別在哪? 原來(lái)的值
原來(lái)的值
角色角度來(lái)看,訂閱發(fā)布模式需要三種角色,發(fā)布者、事件中心和訂閱者。二觀察者模式需要兩種角色,目標(biāo)和觀察者,無(wú)事件中心負(fù)責(zé)通信。
從耦合度上來(lái)看,訂閱發(fā)布模式是一個(gè)事件中心調(diào)度模式,訂閱者和發(fā)布者是沒(méi)有直接關(guān)聯(lián)的,通過(guò)事件中心進(jìn)行關(guān)聯(lián),兩者是解耦的。而觀察者模式中目標(biāo)和觀察者是直接關(guān)聯(lián)的,耦合在一起(有些觀念說(shuō)觀察者是解耦,解耦的是業(yè)務(wù)代碼,不是目標(biāo)和觀察者本身)。
兩者的優(yōu)缺點(diǎn)?優(yōu)缺點(diǎn)都是從前端角度來(lái)看的。
訂閱發(fā)布模式優(yōu)點(diǎn)靈活
由于訂閱發(fā)布模式的發(fā)布者和訂閱者是解耦的,只要引入訂閱發(fā)布模式的事件中心,無(wú)論在何處都可以發(fā)布訂閱。同時(shí)訂閱發(fā)布者相互之間不影響。
訂閱發(fā)布模式在使用不當(dāng)?shù)那闆r下,容易造成數(shù)據(jù)流混亂,所以才有了 React 提出的單項(xiàng)數(shù)據(jù)流思想,就是為了解決數(shù)據(jù)流混亂的問(wèn)題。
訂閱發(fā)布模式缺點(diǎn)容易導(dǎo)致代碼不好維護(hù)
靈活是有點(diǎn),同時(shí)也是缺點(diǎn),使用不當(dāng)就會(huì)造成數(shù)據(jù)流混亂,導(dǎo)致代碼不好維護(hù)。
性能消耗更大
訂閱發(fā)布模式需要維護(hù)事件列隊(duì),訂閱的事件越多,內(nèi)存消耗越大。
觀察者模式優(yōu)點(diǎn)響應(yīng)式
目標(biāo)變化就會(huì)通知觀察者,這是觀察者最大的有點(diǎn),也是因?yàn)檫@個(gè)優(yōu)點(diǎn),觀察者模式在前端才會(huì)這么出名。
觀察者模式缺點(diǎn)不靈活
相比訂閱發(fā)布模式,由于目標(biāo)和觀察者是耦合在一起的,所以觀察者模式需要同時(shí)引入目標(biāo)和觀察者才能達(dá)到響應(yīng)式的效果。而訂閱發(fā)布模式只需要引入事件中心,訂閱者和發(fā)布者可以不再一處(同一個(gè)頁(yè)面)。
參考文章訂閱發(fā)布模式和觀察者模式真的不一樣
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106987.html
摘要:發(fā)布訂閱者模式中,訂閱者是不知道也不關(guān)心事件是為什么觸發(fā),是由哪一個(gè)事件觸發(fā),只知道事件觸發(fā)時(shí)候,會(huì)告訴自己。然而,在發(fā)布訂閱模式中,發(fā)布者和訂閱者不知道對(duì)方的存在。在發(fā)布訂閱模式中,組件是松散耦合的,正好和觀察者模式相反。 概念 發(fā)布訂閱者模式,是javascript甚至大多數(shù)語(yǔ)言都有的語(yǔ)言模式,比較概念的解釋是, 訂閱者把自己想訂閱的事件注冊(cè)到調(diào)度中心,當(dāng)該事件觸發(fā)時(shí)候,發(fā)布者發(fā)布...
摘要:發(fā)布訂閱者模式中,訂閱者是不知道也不關(guān)心事件是為什么觸發(fā),是由哪一個(gè)事件觸發(fā),只知道事件觸發(fā)時(shí)候,會(huì)告訴自己。然而,在發(fā)布訂閱模式中,發(fā)布者和訂閱者不知道對(duì)方的存在。在發(fā)布訂閱模式中,組件是松散耦合的,正好和觀察者模式相反。 概念 發(fā)布訂閱者模式,是javascript甚至大多數(shù)語(yǔ)言都有的語(yǔ)言模式,比較概念的解釋是, 訂閱者把自己想訂閱的事件注冊(cè)到調(diào)度中心,當(dāng)該事件觸發(fā)時(shí)候,發(fā)布者發(fā)布...
摘要:最近被人問(wèn)到設(shè)計(jì)模式,觀察者模式和發(fā)布訂閱模式二者有什么區(qū)別。觀察者模式觀察者模式,目標(biāo)和觀察者是基類(lèi),目標(biāo)提供維護(hù)觀察者的一系列方法,觀察者提供更新接口。 最近被人問(wèn)到設(shè)計(jì)模式,觀察者(Observer)模式和發(fā)布(Publish)/訂閱(Subscribe)模式二者有什么區(qū)別。其實(shí)這兩種模式還是有些許差異的,本質(zhì)上的區(qū)別是調(diào)度的方式不同。 觀察者模式 觀察者模式,目標(biāo)和觀察者是基類(lèi)...
摘要:舉個(gè)例子淘寶商鋪賣(mài)家在淘寶上開(kāi)了一個(gè)相機(jī)店最近都有意愿去買(mǎi)但是覺(jué)得價(jià)格稍貴,因此暫時(shí)不打算入手,想等價(jià)格稍微便宜一點(diǎn)后再入手,所以這個(gè)人通過(guò)淘寶先關(guān)注賣(mài)家的相機(jī)店。等到賣(mài)家的相機(jī)打折后,淘寶會(huì)向這個(gè)人推送打折消息。 Observer觀察者模式 Observer觀察者模式和Pub/sub模式事實(shí)上都是同一套路。這種模式建立起了不同對(duì)象之間的依賴關(guān)系: showImg(https://se...
摘要:細(xì)思不恐主旨在設(shè)計(jì)模式中,觀察者模式的主旨則是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。 簡(jiǎn)單說(shuō)兩句 觀察者模式,是對(duì)象行為型模式中的一種,有的時(shí)候人們也叫他發(fā)布/訂閱模式。當(dāng)我們需要在一個(gè)對(duì)象狀態(tài)改變的時(shí)候通知到其它對(duì)象,這時(shí)候就可以考慮一下觀察者模式。 細(xì)思不恐 showImg(https://segmentfault....
閱讀 1872·2019-08-30 15:53
閱讀 3198·2019-08-30 15:44
閱讀 2811·2019-08-26 13:31
閱讀 1953·2019-08-26 12:10
閱讀 799·2019-08-26 11:01
閱讀 2127·2019-08-23 15:32
閱讀 1588·2019-08-23 13:43
閱讀 2536·2019-08-23 11:58