18910140161

js设计模式"观察者模式"VS"发布/订阅模式模式"有什么区别?

顺晟科技

2021-06-16 10:35:43

431

一、观察者模式(观察者)

观察者模式是指一个Subject维护一系列依赖它的观察者,当相关状态发生变化时,Subject对象通知一系列观察者对象更新。

在观察者模式下,主体对象有添加、删除和通知一系列观察者的方法,而观察者对象有更新方法等。

//定义一个主体对象

课程主题{

constructor() {

这个。观察者=[];

}

Add(观察员){//add

这个。Observers.push(观察者)

}

移除(观察者){//移除

这个。observers . filter(item=item===observer);

}

notify() {

这个。Observers.forEach(item={

item . update();

})

}

}

//定义观察对象

观察者类{

构造函数(名称){

this.name=name

}

update() {

console.log(`我的名字是: $ { this . name } `);

}

}

//测试

let sub=new Subject();

让obs1=新观察者(' leaf 111 ');

让obs2=新观察者(' leaf 222 ');

sub . add(OBS 1);

sub . add(OBS 2);

sub . notify();

在上面的代码中,我们创建了一个主题对象和两个观察者对象。当相关状态发生变化时,我们通过Subject对象的notify方法通知这两个Observer对象,这两个Observer对象通过update方法进行更新。

第二,发布和订阅模式(发布者订阅者)

发布-订阅模式意味着希望接收通知的订阅者通过基于主题的自定义事件订阅主题,激活的事件对象(发布者)通过发布主题事件通知订阅该主题的每个订阅者。

让pubSub={

subs: [],

订阅(密钥,fn) {//订阅

if(!this.subs[key]) {

this . subs[key]=[];

}

this.subs[key]。push(fn);

},

发布(.arg) {//发布

设args=arg

let key=args . shift();

让fns=this . subs[key];

if(!fns || fns.length=0)返回;

for(设i=0,len=fns.lengthi leni ) {

fns[I](args);

}

},

取消订阅(键){

删除this.subs[key]

}

}

//测试

pubSub.subscribe('name ',name={

console.log(`您的名字是$ { name } `);

})

pubSub.subscribe('gender ',gender={

console.log(`您的名字是$ { gender } `);

})

pubSub.publish('name ',' leaf 333 ');//你的名字是leaf333

pubSub.publish('gender ',' 18 ');//你的性别是18

第三,区别

如上图所示:

1.在观察者模式下,观察者知道主体,主体保存观察者的记录。但是,在发布-订阅模式下,发布者和订阅者不知道彼此的存在。他们只通过消息代理进行通信。

2.在发布-订阅模式中,组件是松散耦合的,与观察者模式正好相反。

3.观察者模式大部分时间是同步的。例如,当一个事件被触发时,主体将调用观察者的方法。大多数情况下,发布-订阅模式是异步的(使用消息队列)。

第四,vue的作用

Vue将遍历实例的data属性,将每个数据设置为一个访问器,然后在属性的getter函数中将其设置为一个观察器,并将更改后的消息发布给setter中的其他观察器。

//遍历传入实例的数据对象的属性,并将其设置为Vue对象的访问器属性

功能观察(obj,vm){

Object.keys(obj)。forEach(功能键){

defineReactive(vm,key,obj[key]);

});

}

//被设置为访问器属性,在其getter和setter函数中,使用订阅发布模式。互相倾听。

函数定义活动(对象、键、值){

//这里使用的是观察者模式,定义了一对多的关系,允许多个观察者监视一个主体对象。当主体对象的状态发生变化时,会通知所有观察者,观察者对象可以更新自己的状态。

//用空的观察者列表实例化一个主题对象

var Dep=new Dep();

//将数据的每个属性设置为Vue对象的访问器属性,属性名称与数据中的相同

//所以每次修改Vue.data的时候,都会调用下边的得到和设置方法。然后会监听v型的投入事件,当改变了投入的值,就相应的改变Vue.data的数据,然后触发这里的设置方法

Object.defineProperty(obj,key,{

get: function(){

//Dep.target指针指向观察者,增加订阅者看守人到主体对象资料执行防止

if(Dep.target){

离开AddSub(Dep。目标);

}

返回英国压力单位

},

set:函数(newVal){

if(newVal===val){

返回

}

val=newVal

//控制台。log(val);

//给订阅者列表中的观察者发出通知

离开notify();

}

});

}

//主题对象资料执行防止构造函数

函数Dep(){

这个。subs=[];

}

//Dep有两个方法,增加订阅者和发布消息

Dep.prototype={

addSub:函数(sub){

这个。潜艇。push(sub);

},

notify:函数(){

这个。潜艇。foreach(function(sub){

sub。update();

});

}

}

相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航