观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知
什么是观察者模式?
发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。在 JavaScript 开发中,我们一般用事件模型来替代传统的发布—订阅模式。
举个栗子:
卖水果的张老板和王老板都要进一批香蕉,他们的水果都是在一个叫钱多多(下面统称为钱老板)的水果批发商那里进的。当张老板和王老板到钱老板那里进水果的时候,钱老板告诉张老板和王老板,香蕉还没有到货,得过几天才到货。无奈之下,张老板和王老板都把他们的电话号码留在了钱老板那里,嘱咐钱老板,香蕉到货后,第一时间通知他们。
上面钱老板就扮演了发布者的角色,张老板和王老板则扮演的是订阅者角色。在香蕉到货后,钱老板会主动给张老板和王老发消息,让两位老板来取香蕉。这样的好处就是:香蕉没到的这段时间,张老板和王老板可以做其他的事情,不用主动联系钱老板,只需等待钱老板的消息即可。也就是程序代码中的时间上解耦,对象间解耦。
自定义事件
其实观察者模式我们都曾使用过,就是我们熟悉的事件
但是内置的事件很多时候不能满足我们的要求
所以我们需要自定义事件
现在我们想实现这样的功能 定义一个事件对象,它有以下功能
- 监听事件(订阅事件)
- 触发事件(事件发布)
- 移除事件(取消订阅事件)
当然我们不可能只订阅一个事件,可能会有很多
所以我们要针对不同的事件设置不同的”键”
这样我们储存事件的结构应该是这样的
EventList = {
evtName1: [回调函数1,回调函数2,...],
evtName2: [回调函数1,回调函数2,...],
evtName3: [回调函数1,回调函数2,...],
}
代码如下
var createEventSys = function(){
return {
// 通过on接口监听事件eventName
// 如果事件eventName被触发,则执行callback回调函数
on: function (eventName, callback) {
//如果Event对象没有handles属性,则给Event对象定义属性handles,初始值为{}
//handles属性是用来存储事件和回调执行函数的(即存储订阅的事件和触发事件后执行的相应函数方法)
if(!this.handles){
this.handles={};
}
//如果handles中不存在事件eventName,则将事件存储在handles中,同时初始化该事件对应的回调逻辑函数集合
if(!this.handles[eventName]){
this.handles[eventName]=[];
}
//往handles中的eventName对应的回调逻辑函数集合push回调函数callback
this.handles[eventName].push(callback);
},
// 触发事件 eventName
emit: function (eventName) {
//如果事件eventName有订阅者,则依次执行事件eventName的订阅者相应的回调方法
if(this.handles[arguments[0]]){
for(var i=0;i<this.handles[arguments[0]].length;i++){
this.handles[arguments[0]][i](arguments[1]);
}
}
},
//移除事件 eventName
remove: function (eventName, fn) {
//判断事件eventName是否存在fn这个观察者,如果有,则移除事件eventName的fn观察者
if(this.handles[eventName]){
for(var i=0; i<this.handles[eventName].length; i++){
if(this.handles[eventName][i] === fn){
this.handles[eventName].splice(i,1);
break;
}
}
}
}
};
}
var Event = createEventSys();
Event.on('test', function (result) {
console.log(result);
});
Event.on('test', function () {
console.log('test');
});
Event.emit('test', 'hello world'); // 输出 'hello world' 和 'test'
//对象person1和对象person2拓展复用自定义系统
var person1 = {};
var person2 = {};
Object.assign(person1, createEventSys());
Object.assign(person2, createEventSys());
person1.on('call1', function () {
console.log('person1');
});
person2.on('call2', function () {
console.log('person2');
});
person1.emit('call1'); // 输出 'person1'
person1.emit('call2'); // 没有输出
person2.emit('call1'); // 没有输出
person2.emit('call2'); // 输出 'person2'
如上面代码这样,我们用观察者模式就实现了一个基本完善的自定义事件系统。
总结
观察者模式有两个明显的优点
时间上解耦
对象间解耦
在前端开发中,很多地方都适合用观察者模式来做,在适当的地方善用观察者模式
希望这篇文章对大家有帮助,喜欢的话,请关注我,我会持续更新一些技术文章到我的掘金主页,谢谢大家支持!