以前一直對觀察者模式和發佈訂閱模式的區別理解不深,正好這段時間在看vue源碼的分析,vue數據雙向綁定也用到了發佈訂閱模式,因而又把這二者探究了一番,今天作個筆記增強印象。
觀察者模式和發佈訂閱模式最大的區別就是發佈訂閱模式有個事件調度中心。vue
pubSub.pngthis
從圖中能夠看出,觀察者模式中觀察者和目標直接進行交互,而發佈訂閱模式中統一由調度中心進行處理,訂閱者和發佈者互不干擾。這樣一方面實現瞭解耦,還有就是能夠實現更細粒度的一些控制。好比發佈者發佈了不少消息,可是不想全部的訂閱者都接收到,就能夠在調度中心作一些處理,相似於權限控制之類的。還能夠作一些節流操做。prototype
接下來看一下代碼實現
觀察者模式:雙向綁定
// 觀察者 class Observer { constructor() { } update(val) { } } // 觀察者列表 class ObserverList { constructor() { this.observerList = [] } add(observer) { return this.observerList.push(observer); } remove(observer) { this.observerList = this.observerList.filter(ob => ob !== observer); } count() { return this.observerList.length; } get(index) { return this.observerList(index); } } // 目標 class Subject { constructor() { this.observers = new ObserverList(); } addObserver(observer) { this.observers.add(observer); } removeObserver(observer) { this.observers.remove(observer); } notify(...args) { let obCount = this.observers.count(); for (let index = 0; index < obCount; index++) { this.observers.get(i).update(...args); } } }
發佈訂閱模式:code
class PubSub { constructor() { this.subscribers = {} } subscribe(type, fn) { if (Object.prototype.hasOwnProperty.call(this.subscribers, type)) { this.subscribers[type] = []; } this.subscribers[type].push(fn); } unsubscribe(type, fn) { let listeners = this.subscribers[type]; if (!listeners || !listeners.length) return; this.subscribers[type] = listeners.filter(v => v !== fn); } publish(type, ...args) { let listeners = this.subscribers[type]; if (!listeners || !listeners.length) return; listeners.forEach(fn => fn(...args)); } } let ob = new PubSub(); ob.subscribe('add', (val) => console.log(val)); ob.publish('add', 1);
從上面代碼能夠看出,觀察者模式由具體目標調度,每一個被訂閱的目標裏面都須要有對觀察者的處理,會形成代碼的冗餘。而發佈訂閱模式則統一由調度中心處理,消除了發佈者和訂閱者之間的依賴。server
觀察者模式跟咱們平時用的事件也有必定的關係,好比:事件
ele.addEventListener('click', () => {});
addEventListener就至關於註冊了一個觀察者,當觀察到‘click’事件的時候,做出一些處理。rem
好啦,內容基本就這些,若是有什麼不對的地方,歡迎指正哦~get