发布-订阅模式
定义对象间一对多的依赖关系,当一个对象状态改变将使所有依赖它的对象获得通知。
与直接使用回调函数一样实现异步通信,但可较方便的实现同一事件响应的多个响应者的管理,降低触发者和响应者的耦合。
DOM事件监听即为发布-订阅模式的实现。
// 局部实现发布-订阅通信
(function(win){
// 发布-订阅功能独立封装
var event = {
listenTypes: []
,listen: function( type, fn ){
// 第一次订阅 type 类型
if (!this.listenTypes[type]){
this.listenTypes[type] = [];
}
// 存放 type 类型订阅 的回调函数
this.listenTypes[type].push(fn);
}
,trigger: function(){
var type = Array.prototype.shift.call( arguments ),
callFns = this.listenTypes[type],
fn = null;
// 没有订阅者的回调
if (!callFns || callFns.length === 0){
return false;
}
// 遍历执行订阅者的回调
for (var i in callFns){
fn = callFns[i];
fn.apply(this, arguments);
}
}
,remove: function( type, fn ){
var callFns = this.listenTypes[type];
// 没有该类型订阅,直接返回
if(!callFns){
return true;
}
// 参数只有 type, 处理为取消 类型发布,即取消所有订阅
if(!fn){
console.log("已取消 " + type + " 的发布。");
callFns = [];
}else{
var tempFn = null;
for(var j=callFns.length-1; j>=0; j--){
tempFn = callFns[ j ];
if(tempFn === fn){
// 删除对应的订阅回调
callFns.splice( j, 1 );
}
}
}
}
};
// 给任意对象动态安装发布订阅模式
var installEvent = (function(){
return function(obj){
for (var i in event){
obj[ i ] = event[ i ];
}
};
})();
win.installEvent = installEvent;
})(window);
// 用户A
var userA = {
name: "User A"
,getMsg: function(msg){
console.log(this.name + " get message: " + msg);
}
};
// 用户B
var userB = {
name: "User B"
,getMsg: function(msg){
console.log(this.name + " get message: " + msg);
}
};
// 发布者
var server = {
msgA: "获得地址信息"
,msgB: "失去地址信息"
}
// 安装发布订阅
installEvent(server);
// 用户A 回调
var fn_A = userA.getMsg.bind(userA);
// 用户B 回调
var fn_B = userA.getMsg.bind(userB);
server.listen("planA", fn_A );
server.listen("planB", fn_A );
server.listen("planB", fn_B );
// 发布 "planA" 类型
console.log("发布 planA 类型");
server.trigger("planA", server.msgA);
// 发布 "planB" 类型
console.log("发布 planB 类型");
server.trigger("planB", server.msgB);
// 删除用户A 的 "planB" 订阅
server.remove("planB", fn_A );
// 发布 "planB" 类型
console.log("发布 planB 类型");
server.trigger("planB", server.msgB);
/*输出如下:
发布 planA 类型
User A get message: 获得地址信息
发布 planB 类型
User A get message: 失去地址信息
User B get message: 失去地址信息
发布 planB 类型
User B get message: 失去地址信息
*/
部分代码引用和修改:《JavaScript 设计模式与实践》by曾探,