介绍

中介者模式(Mediator),用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

主要内容来自:http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript

正文

软件开发中,中介者是一个行为设计模式,通过提供一个统一的接口让系统的不同部分进行通信。一般,如果系统有很多子模块需要直接沟通,都要创建一个中央控制点让其各模块通过该中央控制点进行交互。中介者模式可以让这些子模块不需要直接沟通,而达到进行解耦的目的。

打个比方,平时常见的机场交通控制系统,塔台就是中介者,它控制着飞机(子模块)的起飞和降落,因为所有的沟通都是从飞机向塔台汇报来完成的,而不是飞机之前相互沟通。中央控制系统就是该系统的关键,也就是软件设计中扮演的中介者角色。

我们先用伪代码来理解一下:

// 如下代码是伪代码,请不要过分在意代码
// 这里app命名空间就相当于扮演中介者的角色
var app = app || {}; // 通过app中介者来进行Ajax请求
app.sendRequest = function ( options ) {
return $.ajax($.extend({}, options);
} // 请求URL以后,展示View
app.populateView = function( url, view ){
$.when(app.sendRequest({url: url, method: 'GET'})
.then(function(){
//显示内容
});
} // 清空内容
app.resetView = function( view ){
view.html('');
} 在JavaScript里,中介者非常常见,相当于观察者模式上的消息Bus,只不过不像观察者那样通过调用pub/sub的形式来实现,而是通过中介者统一来管理,让我们在观察者的基础上来给出一个例子: 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;
}
}; } ()); 调用代码,相对就简单了: (function (Mediator) { function initialize() { // 默认值
mediator.name = "dudu"; // 订阅一个事件nameChange
// 回调函数显示修改前后的信息
mediator.subscribe('nameChange', function (arg) {
console.log(this.name);
this.name = arg;
console.log(this.name);
});
} function updateName() {
// 广播触发事件,参数为新数据
mediator.publish('nameChange', 'tom'); // dudu, tom
} initialize(); // 初始化
updateName(); // 调用 })(mediator); 中介者和观察者 到这里,大家可能迷糊了,中介者和观察者貌似差不多,有什么不同呢?其实是有点类似,但是我们来看看具体的描述:
观察者模式,没有封装约束的单个对象,相反,观察者Observer和具体类Subject是一起配合来维护约束的,沟通是通过多个观察者和多个具体类来交互的:每个具体类通常包含多个观察者,而有时候具体类里的一个观察者也是另一个观察者的具体类。 而中介者模式所做的不是简单的分发,却是扮演着维护这些约束的职责。 中介者和外观模式 很多人可能也比较迷糊中介者和外观模式的区别,他们都是对现有各模块进行抽象,但有一些微妙的区别。 中介者所做的是在模块之间进行通信,是多向的,但外观模式只是为某一个模块或系统定义简单的接口而不添加额外的功能。系统中的其它模块和外观模式这个概念没有直接联系,可以认为是单向性。 完整的例子 再给出一个完整的例子: <!doctype html>
<html lang="en">
<head>
<title>JavaScript Patterns</title>
<meta charset="utf-8">
</head>
<body>
<div id="results"></div>
<script>
function Player(name) {
this.points = 0;
this.name = name;
}
Player.prototype.play = function () {
this.points += 1;
mediator.played();
};
var scoreboard = { // 显示内容的容器
element: document.getElementById('results'), // 更新分数显示
update: function (score) {
var i, msg = '';
for (i in score) {
if (score.hasOwnProperty(i)) {
msg += '<p><strong>' + i + '<\/strong>: ';
msg += score[i];
msg += '<\/p>';
}
}
this.element.innerHTML = msg;
}
}; var mediator = { // 所有的player
players: {}, // 初始化
setup: function () {
var players = this.players;
players.home = new Player('Home');
players.guest = new Player('Guest');
}, // play以后,更新分数
played: function () {
var players = this.players,
score = {
Home: players.home.points,
Guest: players.guest.points
}; scoreboard.update(score);
}, // 处理用户按键交互
keypress: function (e) {
e = e || window.event; // IE
if (e.which === 49) { // 数字键 "1"
mediator.players.home.play();
return;
}
if (e.which === 48) { // 数字键 "0"
mediator.players.guest.play();
return;
}
}
}; // go!
mediator.setup();
window.onkeypress = mediator.keypress; // 30秒以后结束
setTimeout(function () {
window.onkeypress = null;
console.log('Game over!');
}, 30000);
</script>
</body>
</html> 总结 中介者模式一般应用于一组对象已定义良好但是以复杂的方式进行通信的场合,一般情况下,中介者模式很容易在系统中使用,但也容易在系统里误用,当系统出现了多对多交互复杂的对象群时,先不要急于使用中介者模式,而是要思考一下是不是系统设计有问题。 另外,由于中介者模式把交互复杂性变成了中介者本身的复杂性,所以说中介者对象会比其它任何对象都复杂。 同步与推荐 本文已同步至目录索引:深入理解JavaScript系列 深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。

深入理解JavaScript系列(36):设计模式之中介者模式的更多相关文章

  1. 深入理解JavaScript系列(50):Function模式(下篇)

    介绍 本篇我们介绍的一些模式称为初始化模式和性能模式,主要是用在初始化以及提高性能方面,一些模式之前已经提到过,这里只是做一下总结. 立即执行的函数 在本系列第4篇的<立即调用的函数表达式> ...

  2. 深入理解JavaScript系列(49):Function模式(上篇)

    介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying) ...

  3. 深入理解JavaScript系列

    转自http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 深入理解JavaScript系列(1):编写高质量JavaScript代码 ...

  4. 深入理解JavaScript系列(转自汤姆大叔)

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  5. [转]深入理解JavaScript系列

    文章转自:汤姆大叔-深入理解JavaScript系列文章 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解Ja ...

  6. [转载]深入理解JavaScript系列 --汤姆大叔

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  7. 深入理解JavaScript系列(转载)

    深入理解JavaScript系列 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaSc ...

  8. 深入理解JavaScript系列(38):设计模式之职责链模式

    介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象 ...

  9. 深入理解JavaScript系列(30):设计模式之外观模式

    介绍 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用. 正文 外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦 ...

随机推荐

  1. Socket 简易静态服务器 WPF MVVM模式(一)

    整体代码下载 主要实现功能: Socket的简单应用 可修改IP和端口 显示来访信息 界面设计: 界面采用MVVM设计,很简陋. 前台的主要目的是 输入IP地址 输入端口 输入文件目录 开启监听和停止 ...

  2. 在ubuntu下安装KDE以及完全卸载KDE

    自由转载 ^_^ 同时请注明原文出处:http://www.cnblogs.com/wangvsa/archive/2012/07/22/2603626.html 这是一篇翻译,很多不必要的东西就没翻 ...

  3. Kylin -- Dup key found 问题

    kylin 构建 cube 时,抛出了如下的错误: org.apache.kylin.engine.mr.exception.HadoopShellException: java.lang.Runti ...

  4. 使用C语言封装数组,动态实现增删改查

    myArray.h : #pragma once //包含的时候只包含一次 #include <stdio.h> #include <stdlib.h> #include &l ...

  5. J2EE 的体系结构

    J2EE 即Java2平台企业版,它提供了基于组件的方式来设计.开发.组装和部署企业应用.J2EE使用多层分布式的应用模型,这个多层通常通过三层或四层来实现: 1.客户层,运行在客户计算机上的组件.  ...

  6. 微信小程序之页面之间传递值

    页面之间传值有三种方式 1.url传值 2.本地存储传值 3.全局变量传值 1.url传值: 通过url传值的需要通过option来获取参数值. 更多详情可以访问小程序-navigateTo章节. A ...

  7. 单元测试 + UI测试

    一. 单元测试 简介: 单元测试, 又称模块测试, 是针对程序模块的最小单位来进行测试. 对于过程化变成来说, 一个单元就是单个函数 \ 过程等; 对于面向对象变成来说, 一个单元就是一个方法. 有了 ...

  8. java 关于数组 计数的面试题

    题目:用面向对象的方法求出数组中重复 value 的个数 :  1  出现:1 次3 出现:2 次8 出现:3 次2 出现:4 提供数组 :  int[] arr = {1,4,1,4,2,5,4,5 ...

  9. COCI2017-2018#3 Dojave || 洛谷P4443

    题目传送门............................................................................................... ...

  10. C. Enlarge GCD Codeforces Round #511 (Div. 2)【数学】

    题目: Mr. F has nn positive integers, a1,a2,…,an. He thinks the greatest common divisor of these integ ...