有些人认为观察者模式就是发布订阅模式,实际上观察者模式是包含了订阅发布模式,发布订阅模式只是观察者模式中的一种。观察者模式是观察者和被观察者之间的通讯,而发布订阅模式中间增长了一个中转层,经过第三方来分发信息。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就会去调用观察者的方法。而发布订阅模式大多数时候是异步的。并发