发布-订阅模式又被称为观察者模式,它是定义在对象之间一对多的关系中,当一个对象发生变化,其他依赖于它的对象收到通知。在javascript的开发中,我们一般用事件模型替代发布-订阅模式。
-
document.body.click(); //模拟点击
-
-
document.body.addEventListener('click',function(){
-
-
alert(绑定2);
-
-
},false)};
-
-
document.body.addEventListener('click',function(){
-
-
alert(绑定3);
-
-
},false)};
-
-
document.body.click(); //模拟点击
-
复制代码
我们可以增加更多订阅者,不会对发布者的代码造成影响。注意,标准浏览器下用dispatchEvent实现。
自定义事件
①确定发布者。(例如售票处)
②添加缓存列表,便于通知订阅者。(预订车票列表)
③发布消息。遍历缓存列表。依次触发里面存放的订阅者回调函数(遍历列表,逐个发送短信)。
另外,我们还可以在回调函数填入一些参数,例如车票的价格之类信息。
-
var ticketOffice = {}; //售票处
-
-
ticketOffice.clientList = []; //缓存列表,存放订阅者的回调函数
-
-
ticketOffice.listen =
function (fn) { //增加订阅者
-
this.clientList.push(fn); //订阅的消息添加进缓存列表
-
};
-
-
ticketOffice.trigger =
function () { //发布消息
-
for(var i = 0, fn; fn = this.clientList[i++];){
-
fn.apply(this, arguments); //arguments 是发布消息时带上的参数
-
}
-
}
-
-
下面进行简单测试:
-
-
ticketOffice.listen(
function(time, path){ //小刚订阅消息
-
console.log(
'时间:' + time);
-
console.log(
'路线:' + path);
-
});
-
-
-
ticketOffice.listen(
function(time, path){ //小强订阅消息
-
console.log(
'时间:' + time);
-
console.log(
'路线:' + path);
-
});
-
-
ticketOffice.trigger(
'晚上8:10',
'深圳-上海');
-
ticketOffice.trigger(
'晚上8:10',
'上海-深圳');
-
复制代码
至此,我们实现了一个最简单发布-订阅模式。不过这里存在一些问题,我们运行代码可以看到订阅者接收到了所有发布的消息。我们有必要加个key让订阅者只订阅 自己感兴趣的消息。改写后的代码如下:
-
var ticketOffice = {}; //售票处
-
-
ticketOffice.clientList = []; //缓存列表,存放订阅者的回调函数
-
-
ticketOffice.listen =
function (key, fn) { //增加订阅者
-
if (!this.clientList[key]){
-
this.clientList[key] = [];
-
}
-
this.clientList[key].push(fn); //订阅的消息添加进缓存列表
-
};
-
-
ticketOffice.trigger =
function () { //发布消息
-
var key = Array.prototype.shift.call(arguments), //取出消息类型
-
fns = this.clientList[key]; //取出该消息对应的回调函数集合
-
if (!fns || fns.length === 0) {
-
return
false;
-
}
-
-
for(var i = 0, fn; fn = fns[i++];){
-
fn.apply(this, arguments); //arguments 是发布消息时带上的参数
-
}
-
}
-
-
ticketOffice.listen(
'上海-深圳',
function(time){ //小刚订阅消息
-
console.log(
'小刚时间:' + time);
-
});
-
-
-
ticketOffice.listen(
'深圳-上海',
function(time){ //小强订阅消息
-
console.log(
'小强时间:' + time);
-
});
-
-
ticketOffice.trigger(
'深圳-上海',
'晚上8:00');
-
ticketOffice.trigger(
'上海-深圳',
'晚上8:10');
-
复制代码
这样子,订阅者就可以只订阅自己感兴趣的事件了。
参考资料
《JavaScript 设计模式与开发实践》