有些人認爲觀察者模式就是發佈訂閱模式,實際上觀察者模式是包含了訂閱發佈模式,發佈訂閱模式只是觀察者模式中的一種。觀察者模式是觀察者和被觀察者之間的通訊,而發佈訂閱模式中間增長了一箇中轉層,經過第三方來分發信息。vue
// Subject爲被觀察者,Subject中的狀態(state)改變,就通知 Observer更新 class Subject { constructor() { this.observes = [] this.state = false } // this.observes存儲觀察者 attach(observe){ this.observes.push(observe) } // 狀態改變,通知 Observer 觸發更新 setState(newState){ this.state = newState this.observes.forEach( observer => observer.update(newState)) } } // Observer爲觀察者,觀察Subject的狀態是否改變 class Observer { constructor(name) { this.name = name } // 更新 update(state){ console.log(this.name + ",接收到了通知,被觀察者的屬性變爲 " + state) } } var sub = new Subject() var obs1 = new Observer('觀察者1') var obs2 = new Observer('觀察者2') sub.attach(obs1) sub.attach(obs2) // 被觀察者的狀態改變,觸發觀察者更新 sub.setState(true)
vue中數據劫持中就用到了觀察者模式,data中的屬性一發生變化,就通知view界面更新,從而實現數據驅動,想要進一步瞭解vue底層原理,能夠參考能夠參考github上的一篇文章 ☛ MVVM實現git
// 發佈訂閱 class Events { constructor() { this.sub = {} // 容器 } // 根毫不同 name,訂閱對應函數 $on(name, fn) { const wrap = this.sub[name] || (this.sub[name] = []) wrap.push(fn) } // 遍歷全部相同name的訂閱函數,併發布 $emit(name, ...args) { const fns = this.sub[name] || [] fns.forEach(fn => { fn.apply(this, args) }) } // 銷燬,避免內存泄漏 $of(name){ this.sub[name] = null } } // event 至關於中轉器 const event = new Events() // 訂閱 event.$on('eventname', function (a, b) { console.log(a, b) }) event.$on('eventname', function (a, b) { console.log(a, b) }) // 發佈 event.$emit('eventname', 'a', 'b')
vue中的兄弟組件通訊bus的原理就是發佈訂閱模式,該模式有個缺點,當你訂閱一個消息後,也許此消息最後都未發生,但這個訂閱者會始終存在於內存中。因此該消息不使用的時候,調用$of銷燬,以免內存泄漏。github
總而言之,在觀察者模式中,觀察者(Observer)是知道Subject的,Subject一直保持對觀察者進行記錄。然而,在發佈訂閱模式中,發佈者和訂閱者不知道對方的存在。它們只有經過消息代理進行通訊。觀察者模式大多數時候是同步的,好比當事件觸發,Subject就會去調用觀察者的方法。而發佈訂閱模式大多數時候是異步的。併發