JS設計模式 之 釋出-訂閱模式
阿新 • • 發佈:2022-12-07
1、什麼是釋出-訂閱模式
釋出-訂閱模式是屬於經過解耦合的觀察者模式。
讓多個訂閱者物件同時監聽某一個排程中心,這個排程中心觀察到釋出者發生變化的時候,會通知所有的訂閱者。
涉及的幾個角色:
- 訂閱者:收到通知之後,可以更新自己
- 排程中心:通知訂閱者
- 釋出者:被排程中心監視
比如說我們上淘寶買一樣東西,但是價格有點貴,所以我們可以把它加入淘寶的降價通知功能中去,這樣子,當商家降低該商品的價格的時候,我們就能夠收到對應的淘寶發出的通知。
這時候,淘寶就是一個排程中心,我們買家就是訂閱者,賣家就是釋出者。
2、釋出-訂閱模式有什麼用?
解決了一個物件方式改變其他物件通知的問題,解耦他們之間的依賴關係。
你要買某樣東西,你不需要在一直去關注物品的價格是否降低,會由淘寶來通知你,你只需要等待淘寶的資訊,這樣就實現了你和商家之間的解耦,你都不需要去知道商家的商品是漲價了還是降價了,反正當它一降價,淘寶就去通知你。
如圖所示:
3、釋出-訂閱模式的優點與缺點
優點:
- 解耦。像上方提到過的,通過釋出訂閱模式進行通訊,通訊雙方不需要有任何的聯絡,只需要關注彼此的事件即可。
- 廣泛應用於非同步程式設計當中。在非同步程式設計中,我們是不知道結果什麼時候會返回的,通常的辦法就是通過傳入一個回撥函式,在非同步結束後,呼叫這個回撥函式,有值的話就將值作為回撥的引數傳入。但是在釋出訂閱中,只需要在外部去訂閱一個事件,比方說 'ready' 事件,那麼在非同步結束的時候,就可以釋出 'ready' 這個事件,那麼訂閱方就會執行它訂閱的函式,並且釋出事件也是可以傳遞引數的。
缺點:
-
解耦,將兩個物件解耦不僅是他的優點,也是它的缺點所在
- 因為釋出者不會去關心事件釋出的結果,所以一旦事件釋出結束想要進行反饋就沒有辦法。
- 比方說上方的某個事件釋出之後,訂閱者做出了對應的操作,但是你沒有辦法通知釋出者你執行了什麼操作,你只能通過釋出事件的方式在發一個事件回去。
4、釋出-訂閱模式程式碼實現
// 排程中心 class EventBus { constructor() { // 事件集 this.handles = {}; } // 訂閱事件 on(eventType, handle) { if (!this.handles.hasOwnProperty(eventType)) { this.handles[eventType] = []; } if (typeof handle == 'function') { this.handles[eventType].push(handle); } else { throw new Error('缺少回撥函式'); } return this; // 實現鏈式操作 } // 釋出事件 emit(eventType, ...args) { if (this.handles.hasOwnProperty(eventType)) { this.handles[eventType].forEach((item, key, arr) => { item.apply(null, args); }); } else { throw new Error(eventType + "事件未註冊"); } return this; // 實現鏈式操作 } // 取消訂閱 off(eventType, handle) { if (!this.handles.hasOwnProperty(eventType)) { throw new Error(eventType + "事件未註冊"); } else { this.handles[eventType].forEach((item, key, arr) => { if (item == handle) { arr.splice(key, 1); } }); } return this; // 實現鏈式操作 } } let eventBus = new EventBus(); // 釋出者 class Publisher { constructor() {} lowPrice(price) { // 釋出lowPrice事件 eventBus.emit('lowPrice', price); } } // 訂閱者 class Subscriber { constructor() {} lowPriceHandle(price) { console.log("目前最低價是:" + price + "元"); } getLowPrice() { // 訂閱lowPrice事件 eventBus.on('lowPrice', this.lowPriceHandle); } offLowPrice() { eventBus.off('lowPrice', this.lowPriceHandle); } } // 訂閱者訂閱了關於某個商品最新促銷價的訊息 const subscriber = new Subscriber(); subscriber.getLowPrice(); // 釋出者釋出了某個商品的最新促銷價 const publisher = new Publisher(); publisher.lowPrice(100); // test.html:76 目前最低價是:100元 // 訂閱者取消訂閱 subscriber.offLowPrice(); publisher.lowPrice(200);
學習參考: