代码实现
var mediator = (function(){// Storage for topics that can be broadcast or listened tovar topics = {};// Subscribe to a topic, supply a callback to be executed// when that topic is broadcast to// 订阅消息var subscribe = function( topic, fn ){if ( !topics[topic] ){topics[topic] = [];}topics[topic].push( { context: this, callback: fn } );return this;};// 发布消息var publish = function( topic ){var args;if ( !topics[topic] ){return false;}args = Array.prototype.slice.call( arguments, 1 );for ( var i = 0, l = topics[topic].length; i < l; i++ ) {var subscription = topics[topic][i];subscription.callback.apply( subscription.context, args );}return this;};return {publish: publish,subscribe: subscribe,installTo: function( obj ){obj.subscribe = subscribe;obj.publish = publish;}};}());// 具体应用var mod1 = {run: function(arg) {console.log('mod1 received ' + arg);}};var mod2 = {};var topic = 'myTopic';mediator.installTo(mod1);mediator.installTo(mod2);// mod1订阅消息mod1.subscribe(topic, function(arg) {mod1.run(arg);});// mod2发布消息mod2.publish(topic, 'data');
乍看和前面介绍的[发布/订阅模式]没什么区别,例子中体现的一个区别是任何模块都可以发布消息,而发布/订阅模式中观察者只能被动接收消息,具体差异下面展开详细介绍
由中介者模式实现的插件
http://thejacklawson.com/Mediator.js/index.html提供了一个功能强大的实现,支持topic命名空间、消息冒泡、优先级等等
源码(带注释)见http://thejacklawson.com/Mediator.js/mediator.html,或者github
三.中介者模式与发布/订阅模式
从实现上来看
- 通信方式
中介者模式中每个模块都可以发布消息(中介者本身也可以发布消息),而发布/订阅模式中观察者只能被动的等待消息 - 模块依赖结构
中介者模式是星状结构,中介者是一个“控制点”,而发布/订阅模式中,发布订阅机制本身是一个“控制层”,意味着高层可以通过控制层操作下层模块(虽然高层也可以通过中介者控制下层模块,但这不是星状结构的本意) 信息发布方式
由多对多变成了多对一,所有模块都只能和中介者直接对话
缺点:
单一故障点
这是中介者模式最大的缺点,发布/订阅模式也存在这个缺点,但中介者模式表现得更加锐利(结合“控制点”和“控制层”理解)- 性能下降
模块间必须通过第三方才能交互,相比直接交互肯定存在性能下降,是设计模式共有的副作用 - 逻辑实现难度增加
松散耦合导致系统难以控制,很难通过仅仅关注广播来确定一个系统如何做出反应,必须把完整逻辑拆分到各个Topic下,增加了实现上的复杂度
