发布-订阅模式

小小坤 小小坤     2022-09-13     202

关键词:

发布-订阅模式     

       发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。JavaScript开发中我们一般用事件模型来代替传统的发布-订阅模式

现实中的发布-订阅模式

      小明最近喜欢上吃老北京烧饼,可是到了卖烧饼的地方发现已经卖完了,而且排队的人还很多.幸运的是卖烧饼那个MM看小明长得帅,告诉小明等一会就有烧饼吃啦!可是小明现在还有约会要去,不知道烧饼能什么时候出锅,总不能因为吃烧饼而不去约会吧!这时候小明灵机一动,说烧饼MM把你电话给我吧!我先去忙,等会打电话问你烧饼好了没有。烧饼MM也没想太多,把电话给小明了。后来小龙也来买烧饼,情况跟小明差不多,小龙也把烧饼MM的电话要走了。可是问题就这来了,小明、小龙一会儿打一个电话给烧饼MM,导致烧饼MM很烦,辞职走了不干了。
通过上边的事情我们可以发现,存在好多问题
   第一:卖烧饼的MM应该充当发布者
   第二:小明小龙的电话应该保存在卖烧饼的用户列表中,如果卖烧饼的MM离职,这用户就会丢失
   第三:实际上没有这么笨蛋的销售方式的

卖烧饼的店主可以把小明、小龙的电话记录下来,等店里有烧饼了在通知小龙小明来拿这就是所谓的发布-订阅模式,代码如下:

/*烧饼店*/        
var Sesamecakeshop={
    clienlist:[],//缓存列表
    addlisten:function(fn){//增加订阅者
        this.clienlist.push(fn);
    },
    trigger:function(){//发布消息
        for(var i=0,fn;fn=this.clienlist[i++];){
            fn.apply(this,arguments);
        }
    }
}

/*小明发布订阅*/
Sesamecakeshop.addlisten(function(price,taste){
    console.log("小明发布的"+price+"元,"+taste+"味道的");
});
/*小龙发布订阅*/
Sesamecakeshop.addlisten(function(price,taste){
    console.log("小龙发布的"+price+"元,"+taste+"味道的");
});        

Sesamecakeshop.trigger(10,"椒盐");

       从代码中可以看出,只有小明,小龙预定了烧饼,烧饼店就可以发布消息告诉小龙与小明。但是有个问题不知道大家发现了没有。小明只喜欢椒盐味道的。而小龙只喜欢焦糖味道的。上面的代码就满足不了客户的需求,给客户一种感觉就是,不管我喜欢不喜欢,你都会发给我。如果发布比较多,客户就会感到厌烦,甚至会想删除订阅。下边是对代码进行改良大家可以看看。

            
/*烧饼店*/        
var Sesamecakeshop={
    clienlist:{},/*缓存列表*/
    /**
     * 增加订阅者
     * @key {String} 类型
     * @fn {Function} 回掉函数
     * */
    addlisten:function(key,fn){
        if(!this.clienlist[key]){
            this.clienlist[key]=[];
        }
        this.clienlist[key].push(fn);
    },
    /**
     * 发布消息
     * */
    trigger:function(){
        var key=[].shift.call(arguments),//取出消息类型
            fns=this.clienlist[key];//取出该类型的对应的消息集合
        if(!fns || fns.length===0){
            return false;
        }
        for(var i=0,fn;fn=fns[i++];){
            fn.apply(this,arguments);
        }
    },
    /**
     * 删除订阅
     * @key {String} 类型
     * @fn {Function} 回掉函数
     * */
    remove:function(key,fn){
        var fns=this.clienlist[key];//取出该类型的对应的消息集合
        if(!fns){//如果对应的key没有订阅直接返回
            return false;
        }
        if(!fn){//如果没有传入具体的回掉,则表示需要取消所有订阅
            fns && (fns.length=0);
        }else{
            for(var l=fns.length-1;l>=0;l--){//遍历回掉函数列表
                if(fn===fns[l]){
                    fns.splice(l,1);//删除订阅者的回掉
                }
            }
        }
    }
}

/*小明发布订阅*/
Sesamecakeshop.addlisten("焦糖",fn1=function(price,taste){
    console.log("小明发布的"+price+"元,"+taste+"味道的");
});
/*小龙发布订阅*/
Sesamecakeshop.addlisten("椒盐",function(price,taste){
    console.log("小龙发布的"+price+"元,"+taste+"味道的");
});        

Sesamecakeshop.trigger("椒盐",10,"椒盐");

Sesamecakeshop.remove("焦糖",fn1);//注意这里是按照地址引用的。如果传入匿名函数则删除不了        
            
Sesamecakeshop.trigger("焦糖",40,"焦糖");    

       删除的时候需要注意的是,如果订阅的时候传递的是匿名函数,删除的时候如果传入的也是匿名函数。则删除不了。因为删除时候是按照地址引用删除的。传进去的两个匿名函数,对应的地址引用是不同的。

web前端中使用到的发布-订阅模式

      比如咱们常见的用户身份分别有不同的功能,超级管理员拥有最高权限,可以删除修改任意用户。而普通用户则只能修改自己的账户信息。首先是用户身份验证,验证通过之后对应功能才可以显示。

//登录发布-订阅模式
login={
    clienlist:{},/*缓存列表*/
    /**
     * 增加订阅者
     * @key {String} 类型
     * @fn {Function} 回掉函数
     * */
    addlisten:function(key,fn){
        if(!this.clienlist[key]){
            this.clienlist[key]=[];
        }
        this.clienlist[key].push(fn);
    },
    /**
     * 发布消息
     * */
    trigger:function(){
        var key=[].shift.call(arguments),//取出消息类型
            fns=this.clienlist[key];//取出该类型的对应的消息集合
        if(!fns || fns.length===0){
            return false;
        }
        for(var i=0,fn;fn=fns[i++];){
            fn.apply(this,arguments);
        }
    }
}
//超级管理员修改所有用户
var editall=(function(){
    login.addlisten("loginsucc",function(data){
        editall.setview(data);
    });
    return{
        setview:function(data){
            console.log(data);
            console.log("超级管理员修改所有用户");
        }
    }
})();

//仅仅修改自己
var editOwn=(function(){
    login.addlisten("loginsucc",function(data){
        editOwn.setview(data);
    });
    return{
        setview:function(data){
            console.log(data);
            console.log("仅仅修改自己");
        }
    }
})();

 发布-订阅模式简单封装

var _Event=(function(){
    var clienlist={},
    addlisten,trigger,remove;
    /**
     * 增加订阅者
     * @key {String} 类型
     * @fn {Function} 回掉函数
     * */
    addlisten=function(key,fn){
        if(!clienlist[key]){
            clienlist[key]=[];
        }
        clienlist[key].push(fn);
    };
    /**
     * 发布消息
     * */
    trigger=function(){
        var key=[].shift.call(arguments),//取出消息类型
            fns=clienlist[key];//取出该类型的对应的消息集合
        if(!fns || fns.length===0){
            return false;
        }
        for(var i=0,fn;fn=fns[i++];){
            fn.apply(this,arguments);
        }
    };
    /**
     * 删除订阅
     * @key {String} 类型
     * @fn {Function} 回掉函数
     * */
    remove=function(key,fn){
        var fns=clienlist[key];//取出该类型的对应的消息集合
        if(!fns){//如果对应的key没有订阅直接返回
            return false;
        }
        if(!fn){//如果没有传入具体的回掉,则表示需要取消所有订阅
            fns && (fns.length=0);
        }else{
            for(var l=fns.length-1;l>=0;l--){//遍历回掉函数列表
                if(fn===fns[l]){
                    fns.splice(l,1);//删除订阅者的回掉
                }
            }
        }
    };
    return{
        addlisten:addlisten,
        trigger:trigger,
        remove:remove
    }
})();


_Event.addlisten("jianbing",function(d,all){
    console.log("发布的消息来自:"+d+",具体信息:"+all);
});
_Event.addlisten("jianbing",function(d,all){
    console.log("发布的消息来自:"+d+",具体信息:"+all);
})
_Event.trigger("jianbing","小小坤","前端工程师,擅长JavaScript,喜欢结交更多的前端技术人员,欢迎喜欢技术的你加QQ群:198303871")

总结:

      发布-订阅模式就是常说的观察者模式,在实际开发中非常有用。它的优点是为时间是解耦,为对象之间解构,它的应用非常广泛,既可以在异步编程中也可以帮助我们完成更松的解耦。发布-订阅模式还可以帮助我们实现设计模式,从架构上来看,无论MVC还是MVVC都少不了发布-订阅模式的参与。然而发布-订阅模式也存在一些缺点,创建订阅本身会消耗一定的时间与内存,也许当你订阅一个消息之后,之后可能就不会发生。发布-订阅模式虽然它弱化了对象与对象之间的关系,但是如果过度使用,对象与对象的必要联系就会被深埋,会导致程序难以跟踪与维护。

 


 

设计模式-发布-订阅者模式(代码片段)

1、发布-订阅者设计模式定义定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知观察者模式和发布订阅模式区别观察者模式是由具体目标(发布者/被观察者)调度的,而发... 查看详情

发布-订阅模式

1.什么是发布订阅模式发布订阅模式又叫观察者模式,他是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖他的对象都将得到通知。在javascript开发中,我们一般用事件模型来替代传统的发布-订阅模... 查看详情

发布-订阅模式

发布-订阅模式       发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。JavaScript开发中我们一般用事件模型来代替传... 查看详情

redisredis发布订阅通信模式(发布订阅模式|订阅频道|发布消息|接收消息)(代码片段)

文章目录一、发布订阅模式二、订阅频道三、发布消息四、接收消息一、发布订阅模式Redis中存在一种发布订阅消息通信模式:消息发布者:负责发送消息,订阅者需要订阅该发布者频道;消息订阅者:负责接收消息;订阅者先订阅发布... 查看详情

发布-订阅模式

发布—订阅模式,它定义了一种一对多的依赖关系,当发布者发出一种消息时,所有订阅该消息的任务(回调函数)都将开始执行。订阅是希望在某消息或事件发生时可以执行对应的任务;发布指对外广播告知消息已经到达,所... 查看详情

设计模式:发布订阅模式(代码片段)

发布订阅模式调度中心相关方法订阅取消订阅触发示例调度中心classCenterconstructor()this.message=//订阅on(type,fn)if(this.message[type]===undefined)this.message[type]=[]this.message[type].push(fn)//取消订阅off 查看详情

设计模式:发布订阅模式(代码片段)

发布订阅模式调度中心相关方法订阅取消订阅触发示例调度中心classCenterconstructor()this.message=//订阅on(type,fn)if(this.message[type]===undefined)this.message[type]=[]this.message[type].push(fn)//取消订阅off(type,fn) 查看详情

发布订阅模式和委托

观察者模式/发布订阅模式:发布者有一个接口,订阅者也有一个接口。发布者中有一个列表 List<Observer>mList=newArrayList<>();,该列表中存储着所有订阅此发布的订阅者的信息,订阅者接口中有一个方法update,任何订阅... 查看详情

spring源码之七registerlisteners()及发布订阅模式

Spring源码之七registerListeners()及发布订阅模式大家好,我是程序员田同学。今天带大家解读refresh()方法中的registerListeners()方法,也就是我们经常说的Spring的发布-订阅模式。文章首先举一个发布-订阅模式的样例,然后讲解了发布-... 查看详情

eventbus发布-订阅模式(eventbus组成模块|观察者模式)(代码片段)

文章目录一、发布-订阅模式二、EventBus组成模块三、观察者模式一、发布-订阅模式发布订阅模式:发布者Publisher:状态改变时,向消息中心发送事件;订阅者Subscriber:到消息中心订阅自己关心的事件;消息中心:负责维护一个消息队列,... 查看详情

发布-订阅者模式(观察者模式)(代码片段)

发布订阅者模式还有一些好的列子应用可以看看javascript设计模式与开发实践这本书!!!!!一、发布订阅模式是什么发布订阅者模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,... 查看详情

发布/订阅模式

发布/订阅模式  Pub/Sub模式包含三个角色主题(Topic),发布者(Publisher),订阅者(Subscriber)。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。Pub/Sub的特点每个消息可以有多个消费者发布者和订阅者之... 查看详情

发布订阅模式的理解

发布---订阅模式它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。发布订阅模式的优点:支持简单的广播通信,当对象状态发生改变... 查看详情

发布订阅模式(代码片段)

letfs=require(‘fs‘);//发布订阅发布和订阅没关系中间通过数组进行关联functionEvents()this.callbacks=[];this.results=[];//订阅Events.prototype.on=function(callback)this.callbacks.push(callback);//发布Events.prototype.emit=func 查看详情

观察者模式vs发布-订阅模式

...道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者(Publisher)和订阅者(Subscriber)不知道对方的存在。它们只有通过消息代理(信息中介)进行通信。2.在发布订阅模式中,组件是松散耦合的,正... 查看详情

观察者和发布订阅模式的区别

     观察者模式和发布订阅模式有什么区别?大多数的回答都是:Publishers+Subscribers=ObserverPattern,24种基本的设计模式并没有发布-订阅模式,发布订阅模式属于并发型模式;像典型的Mq;这两种相似单并不可以... 查看详情

activemq入门系列三:发布/订阅模式(代码片段)

...)》中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub&Sub),详细介绍了点对点模式并用代码实例进行说明,今天就介绍下发布/订阅模式。一、理论基础发布/订阅模式的工作示意图:消息生产者将消息... 查看详情

javascript发布订阅pubsub模式

...消息的时候,把订阅的消息push到指定消息的队列中,当发布者发布消息的时候,我们遍历执行push到指定消息队列中的回调事件。varPubsub=(function(){vareventObj={};return{subscribe:function(event,fn){eventObj[event]=fn},publish:function(event 查看详情