javascript设计模式-(发布-订阅模式)

var salesOffices={};//定义售楼处
salesOffices.clientList=[];//缓存列表,存放订阅者的回调函数
salesOffices.listen=function (fn) {//增加订阅者
    this.clientList.push(fn);//订阅的消息添加进缓存列表
};
salesOffices.trigger=function(){//发布消息
    for(var i=0,fn;fn=this.clientList[i++];){
        fn.apply(this, arguments);//fn是发布消息时带上的参数
    }
};
salesOffices.listen(function(price,squareMeter){
    console.log(price);
    console.log(squareMeter);
});
salesOffices.trigger(200000,88);

增加一个key,让订阅者只订阅自己感兴趣的消息。

var salesOffices={};//定义售楼处
salesOffices.clientList=[];//缓存列表,存放订阅者的回调函数
salesOffices.listen=function (key,fn) {
    if(!this.clientList[key]){
        this.clientList[key]=[];//如果还没有订阅过此类消息,该该类消息创建一个缓存列表
    }
    this.clientList.push(fn);//订阅的消息添加进缓存列表
};
salesOffices.trigger=function(){//发布消息
    var key=Array.prototype.shift.call(argments),//取出消息类型
    fns=this.clientList[key];//取出该消息对应的回调函数集合
    if(!fns||fns.length===0){//如果没有订阅该消息,则返回
        return false;
    }
    for(var i=0,fn;fn=this.clientList[i++];){
        fn.apply(this, arguments);//arguments是发布消息时带上的参数
    }
};
salesOffices.listen('squareMeter88',function(price){
    console.log(price);
});
salesOffices.listen('squareMeter110',function(price){
    console.log(price);
});
salesOffices.trigger('squareMeter88',200000);
salesOffices.trigger('squareMeter110',300000);

发布-订阅的通用实现

// 将发布-订阅功能提取出来,放在一个单独的对象里
var event={
    clientList:[],
    listen:function(key,fn){
        if(!this.clientList[key]){
            this.clientList[key]=[];
        }
        this.clientList[key].push(fn);
    },
    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);
        }
    }
};

// 再定义一个installEvent函数,这个函数可以给所有的对象都动态安装发布-订阅功能
var installEvent=function(obj){
    for(var i in event){
        obj[i]=event[i];
    }
};

// 测试
var salesOffices={};
installEvent(salesOffices);
salesOffices.listen('squareMeter88',function(price){
    console.log(price);
})
salesOffices.trigger('squareMeter88',2000000);

取消订阅的事件

event.remove=function (key,fn) {
    var fns=this.clientList[key];
    if(!fns){
        return false;
    }
    if(!fn){
        fns&&(fns.length=0);
    } else {
        for(var l=fns.length-1;l>=0;l--){
            var _fn=fns[l];
            if(_fn===fn){
                fns.splice(l,1);
            }
        }
    }
};
var salesOffices={};
var installEvent=function(obj){
    for(var i in event){
        obj[i]=event[i];
    }
}

installEvent(salesOffices);
salesOffices.listen('squareMeter88',fn1=function(price){ //小明订阅
    console.log(price);
});
salesOffices.listen('squareMeter88',fn2=function(price){ //小红订阅
    console.log(price);
});
salesOffices.remove('squareMeter88',fn1);//删除小明的订阅
salesOffices.trigger('squareMeter88',200000);

添加中介,发布-订阅用一个全局的Event对象来实现,订阅者不需要了解信息来自哪个发布者,发布者也不知道消息会推送给哪些订阅者,Event作为一个类似“中介者”的角色,把订阅者和发布者联系起来。

var Event=(function(){
    var clientList={},
    listen,
    trigger,
    remove;
    listen=function(key,fn){
        if(!clientList[key]){
            clientList[key]=[];
        }
        clientList[key].push(fn);
    };
    trigger=function(){
        var key=Array.prototype.shift.call(arguments),
        fns=clientList[key];
        if(!fns||fns.length===0){
            return false;
        }
        for(var i=0,fn;fn=fns[i++];){
            fn.apply(this,arguments);
        }
    };
    remove=function(key,fn){
        var fns=clientList[key];
        if(!fns){
            return false;
        }
        if(!fn){
            fns&&(fns.length=0);
        } else {
            for(var l=fns.length-1;l>=0;l--){
                var _fn=fns[l];
                if(_fn===fn){
                    fns.splice(l,1);
                }
            }
        }
    };
    return {
        listen:listen,
        trigger:trigger,
        remove:remove
    }
})();
Event.listen('squareMeter88',function(price){
    console.log(price);
});
Event.trigger('squareMeter88',2000000)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值