介绍

中介者模式(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. libcurl坑

    code = curl_easy_setopt(conn, CURLOPT_URL, ca.strUrl.c_str()); 要char* 不能string

  2. 《C#多线程编程实战》2.5 AutoResetEvent

    这个有点像是缩小版的mutex 还是很好理解的 相对mutex 使用的范围可能比较小一点. class Program { static AutoResetEvent work = new AutoR ...

  3. 我的java问题排查工具单

    前言 平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常 ...

  4. Java程序员修炼之路

    作者简介:王成委,CSDN知识库特邀编辑,Java高级工程师,熟悉Java编程语言和Oracle数据库.专注于高并发架构设计和大数据存储方向的研究. 我们为什么选择Java 大多数人选择Java可能只 ...

  5. Jenkins持续集成企业实战系列之Jenkins配置演示-----03

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  6. php 镜像richarvey/nginx-php-fpm的ngnix配置

    1.遇到错误option error_page 405 =200 $request_uri; location ~ ^/(json)/ { # root /data/website/xxxx.com/ ...

  7. SDUT OJ 多项式求和

    多项式求和 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Description 多项式描述 ...

  8. UVA - 11995 模拟

    #include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #i ...

  9. 分布式中为什么要加入redis缓存的理解

    面我们介绍了mybatis自带的二级缓存,但是这个缓存是单服务器工作,无法实现分布式缓存.那么什么是分布式缓存呢?假设现在有两个服务器1和2,用户访问的时候访问了1服务器,查询后的缓存就会放在1服务器 ...

  10. Linux 安装 python3

    1. 安装依赖环境 # yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline- ...