09.08 「讲得明白的设计模式」HTML5开发之JS观察者模式 抹茶妹妹版

好叻,今天就来说说大名鼎鼎观察者模式。

啥是观察者模式呢?这就得从吃瓜群众说起,有些吃瓜群众最近想看强东哥最新状况,就关注了强东哥。有些吃瓜群众想看抹茶妹妹的最新状况,就关注了抹茶妹妹。如果强东哥出了新状况,那关注了强东哥的群众就能立即得到强东哥的信息。

OK,那么我们叫吃瓜群众为订阅者。头条就是发布者,根据订阅的内容,来进行发布。

「讲得明白的设计模式」HTML5开发之JS观察者模式 抹茶妹妹版

因此代码实现该模式,通常需要两个步骤:

1、初始化发布者、订阅者。

2、订阅者需要注册到发布者,发布者发布消息时,依次向订阅者发布消息。

订阅者注册

「讲得明白的设计模式」HTML5开发之JS观察者模式 抹茶妹妹版

发布者发布消息

「讲得明白的设计模式」HTML5开发之JS观察者模式 抹茶妹妹版

观察者模式的理解

我觉得还是发布-订阅模式的叫法更容易我们理解,这就类似我们在微信平台订阅了公众号,当它有新的文章发表后,就会推送给我们所有订阅的人。

我们可以看到这种模式的优点:

  • 我们作为订阅者不必每次都去查看这个公众号有没有新文章发布。
  • 公众号作为发布者会在合适时间通知我们。
  • 我们与公众号之间不再强耦合在一起。公众号不关心谁订阅了它。
  • 不管你是男是女还是宠物狗,它只需要定时向所有订阅者发布消息即可。

很简单的道理,过年的时候,群发祝福短信一定要比挨个发短信方便的多。

自定义事件

其实观察者模式我们都曾使用过,就是我们熟悉的事件。但是内置的事件很多时候不能满足我们的要求,所以我们需要自定义事件。

现在我们想实现这样的功能,定义一个事件对象,它有以下功能:

  • 监听事件(订阅公众号)
  • 触发事件(公众号发布)
  • 移除事件(取订公众号)

当然我们不可能只订阅一个公众号,可能会有很多。所以我们要针对不同的事件设置不同的”键” 。

所以储存事件的结构应该是这样得:

//伪代码
Event = {
name1: [回调函数1,回调函数2,...],
name2: [回调函数1,回调函数2,...],
name3: [回调函数1,回调函数2,...],
}

好,那么就可以根据Event[事件名称]获取这个事件的所有回调函数,通过循环将所有回调函数进行执行。如果上面的原理都理解了,那么我们就很容易理解下面简易的订阅者模式的源码了。

代码如下

var Event = (function(){
var list = {},
listen,
trigger,
remove;
listen = function(key,fn){ //监听事件函数
if(!list[key]){
list[key] = []; //如果事件列表中还没有key值命名空间,创建
}
list[key].push(fn); //将回调函数推入对象的“键”对应的“值”回调数组

};
trigger = function(){ //触发事件函数
var key = Array.prototype.shift.call(arguments); //第一个参数指定“键”
msg = list[key];
if(!msg || msg.length === 0){
return false; //如果回调数组不存在或为空则返回false
}
for(var i = 0; i < msg.length; i++){
msg[i].apply(this, arguments); //循环回调数组执行回调函数
}
};
remove = function(key, fn){ //移除事件函数
var msg = list[key];
if(!msg){
return false; //事件不存在直接返回false
}
if(!fn){
delete list[key]; //如果没有后续参数,则删除整个回调数组
}else{
for(var i = 0; i < msg.length; i++){
if(fn === msg[i]){
msg.splice(i, 1); //删除特定回调数组中的回调函数
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
})();
var fn = function(data){
console.log(data + '的推送消息:xxxxxx......');
}
Event.listen('某公众号', fn);
Event.trigger('某公众号', '2016.11.26');
Event.remove('某公众号', fn);


分享到:


相關文章: