发布订阅和观察者模式的区别
有些人认为观察者模式就是发布订阅模式,实际上观察者模式是包含了订阅发布模式,发布订阅模式只是观察者模式中的一种。观察者模式是观察者和被观察者之间的通信,而发布订阅模式中间增加了一个中转层,通过第三方来分发信息。
观察者模式
// 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实现
电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com
发布订阅模式
// 发布订阅
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销毁,以避免内存泄漏。