Mediator模式

来源:互联网 发布:淘宝网dota2 编辑:程序博客网 时间:2024/06/05 22:32

讲modiator之前,我们先来举个例子,机场飞行控制系统,也就是传说中的塔台,具有绝对的权利,他可以控制任何一架飞机的起飞和降落时间以及地方,而飞机和飞机之前不允许通信,也就是说塔台是机场的核心,mediator就相当于这个塔台。

mediator就是用在程序里有多个模块,而你又不想让各个模块有依赖的话,那通过mediator模式可以达到集中控制的目的。实际场景中也是,mediator封装了很多不想干的模块,让他们通过mediator联系在一起,同时也松耦合他们,使得他们之间必须通过mediator才能通信。

那mediator模式的优点是什么?那就是解耦,如果你之前对观察者模式比较了解的话,那理解下面的mediator图就相对简单多了,下图是一个high level的mediator模式图:


想想一下,各模块是发布者,mediator既是发布者又是订阅者。

  1. Module 1向Mediator广播一个实际,说需要做某事
  2. Mediator捕获消息以后,立即启动处理该消息需要使用的Module 2,Module 2处理结束以后返回信息给Mediator
  3. 与此同时,Mediator也启动了Module 3,当接受Module 2 返回消息的时候自动记录日志到Module 3里

可以看到,各模块之间并没有通信,另外Mediator也可以实现监控各模块状态的功能,例如如果Module 3出错了,Mediator可以暂时只想其它模块,然后重启Module 3,然后继续执行。

回顾一下,可以看到,Mediator的优点是:松耦合的模块由同一的Mediator来控制,模块只需要广播和监听事件就可以了,而模块之间不需要直接联系,另外,一次信息的处理可以使用多个模块,也方便我们以后统一的添加新的模块到现有的控制逻辑里。

确定是:由于所有的模块直接都不能直接通信,所有相对来说,性能方面可能会有少许下降,但是我认为这是值得的。

 

我们根据上面的讲解来一个简单的Demo:

    var mediator = (function(){        var subscribe = function(channel, fn){            if (!mediator.channels[channel]) mediator.channels[channel] = [];            mediator.channels[channel].push({ context: this, callback: fn });            return this;        },             publish = function(channel){            if (!mediator.channels[channel]) return false;            var args = Array.prototype.slice.call(arguments, 1);            for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {                var subscription = mediator.channels[channel][i];                subscription.callback.apply(subscription.context, args);            }            return this;        };             return {            channels: {},            publish: publish,            subscribe: subscribe,            installTo: function(obj){                obj.subscribe = subscribe;                obj.publish = publish;            }        };         }());
然后有2个模块分别调用:

    //Pub/sub on a centralized mediator         mediator.name = "tim";    mediator.subscribe('nameChange', function(arg){            console.log(this.name);            this.name = arg;            console.log(this.name);    });         mediator.publish('nameChange', 'david'); //tim, david              //Pub/sub via third party mediator         var obj = { name: 'sam' };    mediator.installTo(obj);    obj.subscribe('nameChange', function(arg){            console.log(this.name);            this.name = arg;            console.log(this.name);    });         obj.publish('nameChange', 'john'); //sam, john