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