[译] 设计模式:发布/订阅模式解析

原文:Design Patterns:PubSub Explained架构

介绍

这个模式用来做为中间人,一个把发布者和订阅者架接在一块儿的代理。发布者是当完成某些过程的时候触发事件的对象,订阅者是但愿当发布者发布的时候但愿被通知的对象。app

生活中有一个很好地例子,广播电台,人们会把频道调到他们最喜欢的节目。广播站不知道观众听得是什么或者他们正在听什么。他只须要发布他们的节目就能够啦。观众也不知道广播站制做节目的过程。他们只要在他们最喜欢的节目运行的时候把台调到对应的频道或者告知朋友就行。测试

发布/订阅者模式实现了松耦合:你可让发布者发布消息,订阅者接受消息而不是寻找一种方式把两个分离的系统链接在一块儿。this

优点

  • 松耦合prototype

发布者不须要知道订阅者的数量,订阅者听得话题或者订阅者是经过什么方式运行的。他们可以相互独立地运行,这样就可让你分开开发这两部分而不须要担忧对状态或实现的任何细微的影响。设计

  • 可扩展性代理

发布/订阅模式可让系统在不管何时没法负载的时候扩展rest

  • 更干净地设计code

充分地利用好发布/订阅模式,你不得不深刻地思考不一样的组件是如何交互的。这一般会让咱们有更干净地设计由于咱们对解耦和松耦合的强调。对象

  • 灵活性

你不须要担忧不一样的组件是如何组合在一块儿的。只要他们共同遵照一份协议

  • 容易测试

你能够很好地找出发布者或订阅者是否会获得错误的信息

缺点

发布/订阅模式最大的有点是解耦,但同时也是最大的缺点:

  • 中间人也许不会通知系统消息传送的状态。因此咱们没法知道消息传送是成功的仍是失败的。紧耦合是须要保证这一点的。

  • 发布者不知道订阅者的状态,反之亦然,这样的话,你根本不知道在另外一端是否会没有问题?

  • 随着订阅者和发布者数量的增长,不断增长的消息传送回致使架构的不稳定,容易在负载大的时候出问题

  • 攻击者(恶意的发布者)可以入侵系统而且撕开它。这会致使恶意的消息被发布,订阅者可以得到他们之前并不能得到的消息。

  • 更新发布者和订阅者的关系会是一个很难的问题,由于毕竟他们根本不认识对方。

  • 须要中间人/代理商,消息规范和相关的规则会给系统增长一些复杂度

结论

现实没有银弹,可是这个模式是设计松耦合系统的很好地方式。这和RSS,Atom和PubSubHubbub的思想同样。

发布/订阅模式例子(Javascript)

var makePubSub=function(){
    var callbacks={},
    publish=function(){
        //Turn arguments object into real array
        var args=Array.prototype.slice.call(arguments,0);

        //Extract the event name which is the first entry
        var ev=args.shift();

        //Return if callbacks object doesn't contain
        //any entry for event
        var list,i,l;
        if(!callbacks[ev]){
            return this;
        }
        list=callbacks[ev];

        //Invoke the callbacks,passing in the rest of parameters
        for(i=0,l=list.length;i<l;i++){
            list[i].apply(this,args);
        }

        return this;
    },
    subscribe=function(ev,callback){
        //Check if ev is already registered
        //If it isn't create an array entry for it
        if(!callbacks[ev]){
            callbacks[ev]=[];
        }
        callbacks[ev].push(callback);
        return this;
    };

    return {pub:publish,sub:subscribe};
}

test=makePubSub();
test.sub("alert",function(){alert("hell0");})
test.pub("alert");
相关文章
相关标签/搜索