代码实现

  1. var mediator = (function(){
  2. // Storage for topics that can be broadcast or listened to
  3. var topics = {};
  4. // Subscribe to a topic, supply a callback to be executed
  5. // when that topic is broadcast to
  6. // 订阅消息
  7. var subscribe = function( topic, fn ){
  8. if ( !topics[topic] ){
  9. topics[topic] = [];
  10. }
  11. topics[topic].push( { context: this, callback: fn } );
  12. return this;
  13. };
  14. // 发布消息
  15. var publish = function( topic ){
  16. var args;
  17. if ( !topics[topic] ){
  18. return false;
  19. }
  20. args = Array.prototype.slice.call( arguments, 1 );
  21. for ( var i = 0, l = topics[topic].length; i < l; i++ ) {
  22. var subscription = topics[topic][i];
  23. subscription.callback.apply( subscription.context, args );
  24. }
  25. return this;
  26. };
  27. return {
  28. publish: publish,
  29. subscribe: subscribe,
  30. installTo: function( obj ){
  31. obj.subscribe = subscribe;
  32. obj.publish = publish;
  33. }
  34. };
  35. }());
  36. // 具体应用
  37. var mod1 = {
  38. run: function(arg) {
  39. console.log('mod1 received ' + arg);
  40. }
  41. };
  42. var mod2 = {};
  43. var topic = 'myTopic';
  44. mediator.installTo(mod1);
  45. mediator.installTo(mod2);
  46. // mod1订阅消息
  47. mod1.subscribe(topic, function(arg) {
  48. mod1.run(arg);
  49. });
  50. // mod2发布消息
  51. mod2.publish(topic, 'data');

乍看和前面介绍的[发布/订阅模式]没什么区别,例子中体现的一个区别是任何模块都可以发布消息,而发布/订阅模式中观察者只能被动接收消息,具体差异下面展开详细介绍

由中介者模式实现的插件

http://thejacklawson.com/Mediator.js/index.html提供了一个功能强大的实现,支持topic命名空间、消息冒泡、优先级等等
源码(带注释)见http://thejacklawson.com/Mediator.js/mediator.html,或者github

三.中介者模式与发布/订阅模式

从实现上来看

  1. 通信方式
    中介者模式中每个模块都可以发布消息(中介者本身也可以发布消息),而发布/订阅模式中观察者只能被动的等待消息
  2. 模块依赖结构
    中介者模式是星状结构,中介者是一个“控制点”,而发布/订阅模式中,发布订阅机制本身是一个“控制层”,意味着高层可以通过控制层操作下层模块(虽然高层也可以通过中介者控制下层模块,但这不是星状结构的本意)
  3. 信息发布方式
    多对多变成了多对一,所有模块都只能和中介者直接对话

    缺点:

  4. 单一故障点
    这是中介者模式最大的缺点,发布/订阅模式也存在这个缺点,但中介者模式表现得更加锐利(结合“控制点”和“控制层”理解)

  5. 性能下降
    模块间必须通过第三方才能交互,相比直接交互肯定存在性能下降,是设计模式共有的副作用
  6. 逻辑实现难度增加
    松散耦合导致系统难以控制,很难通过仅仅关注广播来确定一个系统如何做出反应,必须把完整逻辑拆分到各个Topic下,增加了实现上的复杂度