一文讲解发布者订阅者模式与观察者模式

区别

 观察者模式:当对象之间存在一对多的依赖关系时,其中一个对象的状态发生改变,所有依赖它的对象都会收到通知,这就是观察者模式。
 发布者订阅者模式:基于一个事件通道,希望接收通知的对象Subscriber 通过自定义事件订阅主题,被激活事件的对象 Publisher 通过发布主题事件的方式通知订阅者该主题的 Subscriber 对象。
 观察者模式是,当被观察者的数据发生变化时,调用被观察者的notify方法,去通知所有观察者执行update方法进行更新。对于发布者订阅者模式,首先发布者与订阅者互相并不知道彼此的存在,他们是通过事件中心来进行调度的,发布者在事件中心发布一个对应的事件主题,订阅者在事件中心订阅一个事件主体,当订阅者去触发emit时就去执行发布者所发布的事件。
 Vue展示了其设计模式的案例体现,Vue的双向数据绑定使用了观察者模式,其事件总线EventBus使用了发布者订阅者模式。

实现

手写发布者订阅者模式

class EventEmitter {
    
    

    constructor() {
    
    
        this.events = {
    
    }
    }
    on(name, fn) {
    
    
        if (this.events[name]) {
    
    
            this.events[name].push(fn)
        } else {
    
    
            this.events[name] = [fn]
        }
    }
    off(name, fn) {
    
    
        this.events[name] = this.events[name].filter(event => event != fn)
    }
    once(name, fn) {
    
    
        let one = (...args) => {
    
    
            fn(...args)
            this.off(name, one)
        }
        this.on(name, one)
    }
    emit(name, ...args) {
    
    
        this.events[name].forEach(event => {
    
    
            event.apply(this, args)
        })
    }

}

let ev = new EventEmitter()

let func = function () {
    
    
    console.log("我是小刘")
}

ev.on("name",func)

ev.once("name1", function () {
    
    
    console.log("我是小李")
})
ev.emit("name1")

ev.emit("name")
// 注销对应的事件
ev.off("name", func)
// 触发对应的事件
ev.emit("name")

手写观察者模式

// 被观察的目标,即发布者:Dep
// 被观察的目标,即发布者:Dep
class Dep {
    
    
    constructor() {
    
    
        // 记录所有的观察者,即订阅者
        this.subs = []
    }
    // 添加新的观察者
    addSub(sub) {
    
    
        // 该订阅者存在且有update方法,就将其添加到subs数组中
        if (sub && sub.update) {
    
    
            this.subs.push(sub)
        }
    }
    // 移除观察者
    removeSub(sub) {
    
    
        if (this.subs.length) {
    
    
            let index = this.subs.indexOf(sub)
            if (index > -1) {
    
    
                this.subs.splice(index, 1)
            }
        }
    }
    // 发布更新通知
    notify() {
    
    
        this.subs.forEach(item => {
    
    
            item.update()
        })
    }
}

// 观察者,即订阅者
class Watcher {
    
    
    update() {
    
    
        console.log("****更新相关数据****")
    }
}

let dep = new Dep
let watcher1 = new Watcher()
let watcher2 = new Watcher()

// 添加新的观察者
dep.addSub(watcher1)
dep.addSub(watcher2)
dep.removeSub(watcher2)
// 发布
dep.notify()

猜你喜欢

转载自blog.csdn.net/liu19721018/article/details/125494633