您的位置:首页 > Web前端 > JavaScript

JavaScript设计模式-发布订阅模式

2017-09-07 16:03 246 查看
何为设计模式?

设计模式其实可以认为是大家约定俗成的一个东西,比如在篮球场上的一些术语,在篮球场上争分夺秒的时候,不可能教练一步一步指导你去怎么做,而是告诉你一个术语,你立马就能反应出来该怎么做。这就是设计模式的现实版例子。在JavaScript开发中,有很多设计模式,经常面试也会被问到一些,比如说发布/订阅者模式,单例模式,迭代器模式等等。今天就先拔一拔发布/订阅模式。

发布/订阅模式与我们JavaScript事件处理很像,因为我们不知道事件什么时候会发生,所以注册一个事件处理程序,等到事件发生了,再去执行之前注册的回调函数。发布/订阅模式与她非常类似。我们先想一下,为什么需要发布/订阅模式?

比如这么一种情况:

我去商场买鞋子,看上了一双特别喜欢的,但是号码没有合适的,然后店员跟我说可以把电话号码留下来,到时候有货了跟我说。另一方面,小明,小红也看上了这双鞋子,也没有合适的号码(同样大小),同样把电话号码留给店员。这样,等鞋子到货之后,店员只需要给当初记下的电话号码发短信,我们三个人就会知道鞋子到货了,决定要不要去买。这就是一个典型的发布/订阅模式。店员就相当于发布者,我们三个就是订阅者,订阅了鞋子到货这一消息。当鞋子到货的时候,发布者就会根据当时留下的手机号码依次发布鞋子到货这一消息。有什么好处呢?

一方面,想买鞋子的人不用常常去那家店或者打电话问,鞋子有没有到货;

另一方面:店员也不关注买鞋子的人是谁,是男是女,只要把消息发布出去就可以了。

发布/订阅模式的应用

最常见的应该就是事件处理函数了。看下面一个例子:

<head>
<script>
window.onload = function(){
function handler(){
alert('点击事件');
}
//订阅者订阅点击事件,订阅时,说明点击之后的回调函数
document.getElementById('ddd').addEventListener( 'click', handler, false);
//发布点击事件
document.getElementById('ddd').click();
}
</script>
</head>
<body>
<input id="ddd" type="text" />
</body>


自定义事件

除了DOM事件,还可以自定义事件,这个可以通过JavaScript来模拟实现。

首先,我们要确定发布者,然后定义一个缓存列表,订阅者订阅时,将回调函数存入缓存列表中,便于发布时,遍历缓存列表依次触发订阅者回调函数。看一个简单的实现:

var pubObj = {};
pubObj.list = [];
pubObj.listen = function(fn){
this.list.push(fn);
}

pubObj.publish = function(){
for(var i = 0; i < this.list.length; i++)
{
this.list[i].apply(this, arguments);
}
}

//测试
pubObj.listen(function( size ) {   //小明订阅消息
console.log('到货鞋子号码为' + size );
});
pubObj.listen(function( size ){    //我订阅消息
console.log('到货鞋子号码为'+ size);
})
pubObj.publish(36);
pubObj.publish(38);






可以看到虽然我只订阅36的鞋子到货的消息,但同时也收到了38鞋子到货的消息,这时候怎么去优化呢?我们可以设一个key(或者topic),针对不同的主题有不同的订阅回调,也就是订阅不同,存到不同的缓存列表里面。具体实现如下:

var pubObj = {};
pubObj.list = {};
pubObj.listen = function(key, fn){
if(!this.list[key])
{
this.list[key] = [];
}
this.list[key].push(fn);
}

pubObj.publish = function(){
key = Array.prototype.shift.call(arguments);
if(this.list[key] && this.list[key].length > 0)
{
for(var i = 0; i < this.list[key].length; i++)
{
this.list[key][i].apply(this, arguments);
}
}
else
{
return false;
}
}

//测试
pubObj.listen('size38', function( size ) {   //小明订阅消息
console.log('到货鞋子号码为' + size );
});
pubObj.listen('size36', function( size ){    //我订阅消息
console.log('到货鞋子号码为'+ size);
})
pubObj.publish(36);
pubObj.publish(38);




发布/订阅模式暂时先理解到这里,后续还有通用的发布订阅模式,以及一个小例子的应用,后面会再整理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 设计模式