观察者模式和发布订阅模式

观察者模式和发布订阅模式

观察者模式

观察者模式定义了对象见一种一对多的依赖关系,当一个对象的状态发生改变的时候,所以依赖它的对象都将接收到通知,并作出更新。

发布订阅模式

发布订阅模式,个人理解为是观察者模式的一种特例。最初的时候,订阅目标和订阅对象是联系在一起的,当订阅目标发生改变的时候,会逐个通知订阅者。
在现在的发布订阅模式中,发布者不在直接将消息发送给订阅者,而是是通过一个第三方组件,也称为消息中心或者调度中心,由它来维持着发布者和订阅者之间的通讯,发布方和订阅方互不知道对方的存在。

区别

image.png

观察者模式

订阅者直接订阅发布者的事件,当发布者的状态改变时,会直接触发订阅者的回调事件。

发布订阅模式

订阅者首先将即将订阅的事件注册到调度中心,当发布者发布该事件到调度中心,也就是该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码。

举例

观察者模式

function Hunter(level,name){
    this.name = name;
    this.level = level;
    this.list = [];
};
//发布
Hunter.prototype.publish = function(money){
    console.log(this.level + '猎人,' + this.name + '寻求帮助!!!');
    this.list.forEach(item => {
        item(money)
    })
};
//订阅
Hunter.prototype.subscribe = function(target,fn){
    console.log(this.name + '订阅了' + target.name);
    target.list.push(fn);
};

let kaka = new Hunter('黄金','kaka');
let hudie = new Hunter('钻石','hudie');
let dida = new Hunter('王者','dida');

hudie.subscribe(kaka,(money) => {
    console.log('观察到kaka的动态,向您汇报!')
});

kaka.publish(200)

这上面的代码中,我们定义来一个函数Hunter,在其原型上注册了发布和订阅的函数。在订阅函数中,设置了两个参数,target对象和回调函数fn,然后在发布者的执行队列中将回调函数注入进去。在发布函数中,一旦发布者改变了状态,则会触发其执行队列中的回调函数。

发布订阅模式

let HunterUnion = {
    type:'hunter',
    topics:Object.create(null),
    publish:function(topic,money){
        if(!this.topics[topic]){
            return 
        };
        this.topics[topic].forEach(item => {
            item(money);
        })
    },
    subscribe:function(topic,fn){
        if(!this.topics[topic]){
            this.topics[topic] = [];
        }
        this.topics[topic].push(fn);
    }
}


function Hunter(level,name){
    this.name = name;
    this.level = level;
    this.list = [];
};
//发布
Hunter.prototype.publish = function(topic,money){
    console.log(this.level + '猎人,' + this.name + '发布tiger任务!!!');
    HunterUnion.publish(topic,money)
};
//订阅
Hunter.prototype.subscribe = function(topic,fn){
    console.log(this.name + '订阅了' + topic);
    HunterUnion.subscribe(topic,fn)
    // target.list.push(fn);
};

let kaka = new Hunter('黄金','kaka');
let hudie = new Hunter('钻石','hudie');
let dida = new Hunter('王者','dida');

hudie.subscribe('tiger',(money) => {
    console.log('hudie,' + '观察到tiger的动态,向您汇报!')
});

dida.subscribe('tiger',(money) => {
    console.log('dida,' + '观察到tiger的动态,向您汇报!')
});

kaka.publish('tiger',200)

在上面我们定义了一个调度中心HunterUnion,所有的发布订阅的动作,都在其内部完成。其他大致和上面的观察者差不多。

总结

观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。
观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,这种处理方式比较直接粗暴,但是会造成代码的冗余。
而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰,消除了发布者和订阅者之间的依赖。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!