JavaScript设计模式之中介者模式详解

目录
  • 中介者模式
  • 现实中的中介者
  • 中介者模式的例子
    • 泡泡堂游戏
      • 为游戏增加队伍
      • 玩家增多带来的困扰
      • 用中介者模式改造泡泡堂游戏
  • 小结

中介者模式

在我们生活的世界中,每个人每个物体之间都会产生一些错综复杂的联系。在应用程序里也是一样,程序由大大小小的单一对象组成,所有这些对象都按照某种关系和规则来通信。

平时我们大概能记住 10 个朋友的电话、30 家餐馆的位置。在程序里,也许一个对象会和其他 10 个对象打交道,所以它会保持 10 个对象的引用。当程序的规模增大,对象会越来越多,它们之间的关系也越来越复杂,难免会形成网状的交叉引用。当我们改变或删除其中一个对象的时候,很可能需要通知所有引用到它的对象。这样一来,就像在心脏旁边拆掉一根毛细血管一般, 即使一点很小的修改也必须小心翼翼,如下图所示。

面向对象设计鼓励将行为分布到各个对象中,把对象划分成更小的粒度,有助于增强对象的可复用性,但由于这些细粒度对象之间的联系激增,又有可能会反过来降低它们的可复用性。

中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。中介者模式使网状的多对多关系变成了相对简单的一对多关系,如下图所示。

在前面的图中,如果对象 A 发生了改变,则需要同时通知跟 A 发生引用关系的 B、D、E、F 这 4 个对象;而在上图中,使用中介者模式改进之后,A 发生改变时则只需要通知这个中介者对象即可。

现实中的中介者

在现实生活中也有很多中介者的例子,例如机场指挥塔。

中介者也被称为调停者,我们想象一下机场的指挥塔,如果没有指挥塔的存在,每一架飞机要和方圆 100 公里内的所有飞机通信,才能确定航线以及飞行状况,后果是不可想象的。现实中的情况是,每架飞机都只需要和指挥塔通信。指挥塔作为调停者,知道每一架飞机的飞行状况,所以它可以安排所有飞机的起降时间,及时做出航线调整。

下面我们来看中介者模式在下面这个案例中的应用。

中介者模式的例子

泡泡堂游戏

大家可能都还记得泡泡堂游戏,现在我们来一起回顾这个游戏,假设在游戏之初只支持两个玩家同时进行对战。

先定义一个玩家构造函数,它有 3 个简单的原型方法:Play.prototype.winPlay.prototype.lose 以及表示玩家死亡的 Play.prototype.die

因为玩家的数目是 2,所以当其中一个玩家死亡的时候游戏便结束, 同时通知它的对手胜利。 这段代码看起来很简单:

function Player(name) {
	this.name = name
	this.enemy = null; // 敌人
};
Player.prototype.win = function () {
	console.log(this.name + ' won ');
};
Player.prototype.lose = function () {
	console.log(this.name + ' lost');
};
Player.prototype.die = function () {
	this.lose();
	this.enemy.win();
};

接下来创建 2 个玩家对象:

const player1 = new Player('玩家一');
const player2 = new Player('玩家二');

给玩家相互设置敌人:

player1.enemy = player2;
player2.enemy = player1;

当玩家 player1 被泡泡炸死的时候,只需要调用这一句代码便完成了一局游戏:

player1.die();// 输出:玩家一 lost、玩家二 won

然而真正的泡泡堂游戏至多可以有 8 个玩家,并分成红蓝两队进行游戏。

为游戏增加队伍

现在我们改进一下游戏。因为玩家数量变多,用下面的方式来设置队友和敌人无疑很低效:

player1.partners = [player1, player2, player3, player4];
player1.enemies = [player5, player6, player7, player8];
Player5.partners = [player5, player6, player7, player8];
Player5.enemies = [player1, player2, player3, player4];

所以我们定义一个数组 players 来保存所有的玩家,在创建玩家之后,循环 players 来给每个玩家设置队友和敌人:

const players = []; 

再改写构造函数 Player,使每个玩家对象都增加一些属性,分别是队友列表、敌人列表 、 玩家当前状态、角色名字以及玩家所在的队伍颜色:

function Player(name, teamColor) {
	this.partners = []; // 队友列表
	this.enemies = []; // 敌人列表
	this.state = 'live'; // 玩家状态
	this.name = name; // 角色名字
	this.teamColor = teamColor; // 队伍颜色
};

玩家胜利和失败之后的展现依然很简单,只是在每个玩家的屏幕上简单地弹出提示:

Player.prototype.win = function () { // 玩家团队胜利
	console.log('winner: ' + this.name);
};
Player.prototype.lose = function () { // 玩家团队失败
	console.log('loser: ' + this.name);
};

玩家死亡的方法要变得稍微复杂一点,我们需要在每个玩家死亡的时候,都遍历其他队友的生存状况,如果队友全部死亡,则这局游戏失败,同时敌人队伍的所有玩家都取得胜利,代码如下:

Player.prototype.die = function () { // 玩家死亡
	let all_dead = true;
	this.state = 'dead'; // 设置玩家状态为死亡
	for (let i = 0; i < this.partners.length; i++) { // 遍历队友列表
		if (this.partners[i].state !== 'dead') { // 如果还有一个队友没有死亡,则游戏还未失败
			all_dead = false;
			break;
		}
	}
	if (all_dead === true) { // 如果队友全部死亡
		this.lose(); // 通知自己游戏失败
		for (let i = 0; i < this.partners.length; i++) { // 通知所有队友玩家游戏失败
			this.partners[i].lose();
		}
		for (let i = 0; i < this.enemies.length; i++) { // 通知所有敌人游戏胜利
			this.enemies[i].win();
		}
	}
};

最后定义一个工厂来创建玩家:

const playerFactory = function (name, teamColor) {
	const newPlayer = new Player(name, teamColor); // 创建新玩家
	for (let i = 0; i < players.length; i++) { // 通知所有的玩家,有新角色加入
		if (players[i].teamColor === newPlayer.teamColor) { // 如果是同一队的玩家
			players[i].partners.push(newPlayer); // 相互添加到队友列表
			newPlayer.partners.push(players[i]);
		} else {
			players[i].enemies.push(newPlayer); // 相互添加到敌人列表
			newPlayer.enemies.push(players[i]);
		}
	}
	players.push(newPlayer);
	return newPlayer;
};

现在来感受一下, 用这段代码创建 8 个玩家:

//红队:
var player1 = playerFactory('皮蛋', 'red'),
	player2 = playerFactory('小乖', 'red'),
	player3 = playerFactory('宝宝', 'red'),
	player4 = playerFactory('小强', 'red');
//蓝队:
var player5 = playerFactory('黑妞', 'blue'),
	player6 = playerFactory('葱头', 'blue'),
	player7 = playerFactory('胖墩', 'blue'),
	player8 = playerFactory('海盗', 'blue');

让红队玩家全部死亡:

player1.die();
player2.die();
player4.die();
player3.die();

结果如下:

loser: 宝宝
loser: 皮蛋
loser: 小乖
loser: 小强
winner: 黑妞
winner: 葱头
winner: 胖墩
winner: 海盗

玩家增多带来的困扰

现在我们已经可以随意地为游戏增加玩家或者队伍,但问题是,每个玩家和其他玩家都是紧紧耦合在一起的。在此段代码中,每个玩家对象都有两个属性,this.partnersthis.enemies,用来保存其他玩家对象的引用。当每个对象的状态发生改变,比如角色移动、吃到道具或者死亡时,都必须要显式地遍历通知其他对象。

在这个例子中只创建了 8 个玩家,或许还没有对你产生足够多的困扰,而如果在一个大型网络游戏中,画面里有成百上千个玩家,几十支队伍在互相厮杀。如果有一个玩家掉线,必须从所有其他玩家的队友列表和敌人列表中都移除这个玩家。游戏也许还有解除队伍和添加到别的队伍的功能,红色玩家可以突然变成蓝色玩家,这就不再仅仅是循环能够解决的问题了。面对这样的需求,我们上面的代码可以迅速进入投降模式。

用中介者模式改造泡泡堂游戏

现在我们开始用中介者模式来改造上面的泡泡堂游戏, 改造后的玩家对象和中介者的关系如下图所示。

首先仍然是定义 Player 构造函数和 player 对象的原型方法,在 player 对象的这些原型方法 中,不再负责具体的执行逻辑,而是把操作转交给中介者对象,我们把中介者对象命名为 playerDirector

function Player(name, teamColor) {
	this.name = name; // 角色名字
	this.teamColor = teamColor; // 队伍颜色
	this.state = 'alive'; // 玩家生存状态
};
Player.prototype.win = function () {
	console.log(this.name + ' won ');
};
Player.prototype.lose = function () {
	console.log(this.name + ' lost');
};
/*******************玩家死亡*****************/
Player.prototype.die = function () {
	this.state = 'dead';
	playerDirector.reciveMessage('playerDead', this); // 给中介者发送消息,玩家死亡
};
/*******************移除玩家*****************/
Player.prototype.remove = function () {
	playerDirector.reciveMessage('removePlayer', this); // 给中介者发送消息,移除一个玩家
};
/*******************玩家换队*****************/
Player.prototype.changeTeam = function (color) {
	playerDirector.reciveMessage('changeTeam', this, color); // 给中介者发送消息,玩家换队
};

再继续改写之前创建玩家对象的工厂函数,可以看到,因为工厂函数里不再需要给创建的玩家对象设置队友和敌人,这个工厂函数几乎失去了工厂的意义:

const playerFactory = function (name, teamColor) {
	const newPlayer = new Player(name, teamColor); // 创造一个新的玩家对象
	playerDirector.reciveMessage('addPlayer', newPlayer); // 给中介者发送消息,新增玩家
	return newPlayer;
};

最后,我们需要实现这个中介者 playerDirector 对象,一般有以下两种方式。

  • 利用发布—订阅模式。将 playerDirector 实现为订阅者,各 player 作为发布者,一旦 player 的状态发生改变,便推送消息给 playerDirectorplayerDirector 处理消息后将反馈发送 给其他 player
  • playerDirector 中开放一些接收消息的接口,各 player 可以直接调用该接口来给 playerDirector 发送消息,player 只需传递一个参数给 playerDirector,这个参数的目的是使 playerDirector 可以识别发送者。同样,playerDirector 接收到消息之后会将处理结果反馈给其他 player

这两种方式的实现没什么本质上的区别。在这里我们使用第二种方式,playerDirector 开放一个对外暴露的接口 reciveMessage,负责接收 player 对象发送的消息,而 player 对象发送消息的时候,总是把自身 this 作为参数发送给 playerDirector,以便 playerDirector 识别消息来自于哪个玩家对象,代码如下:

const playerDirector = (function () {
	const players = {}, // 保存所有玩家
		operations = {}; // 中介者可以执行的操作
	/**
	 * 新增一个玩家
	 * @param {Player} player 玩家
	 */
	operations.addPlayer = function (player) {
		const teamColor = player.teamColor; // 玩家的队伍颜色
		// 如果该颜色的玩家还没有成立队伍,则新成立一个队伍
		players[teamColor] = players[teamColor] || [];
		players[teamColor].push(player); // 添加玩家进队伍
	};
	/**
	 * 移除一个玩家
	 * @param {Player} player 玩家
	 */
	operations.removePlayer = function (player) {
		const teamColor = player.teamColor, // 玩家的队伍颜色
			teamPlayers = players[teamColor] || []; // 该队伍所有成员
		for (let i = teamPlayers.length - 1; i >= 0; i--) { // 遍历删除
			if (teamPlayers[i] === player) {
				teamPlayers.splice(i, 1);
			}
		}
	};
	/**
	 * 玩家换队
	 * @param {Player} player 玩家
	 * @param {string} newTeamColor 队伍颜色
	 */
	operations.changeTeam = function (player, newTeamColor) { // 玩家换队
		operations.removePlayer(player); // 从原队伍中删除
		player.teamColor = newTeamColor; // 改变队伍颜色
		operations.addPlayer(player); // 增加到新队伍中
	};
	/**
	 * 玩家死亡
	 * @param {Player} player 玩家
	 */
	operations.playerDead = function (player) {
		const teamColor = player.teamColor,
			teamPlayers = players[teamColor]; // 玩家所在队伍
		let all_dead = true;
		for (let i = 0; i < teamPlayers.length; i++) {
			if (teamPlayers[i].state !== 'dead') {
				all_dead = false;
				break;
			}
		}
		if (all_dead) { // 全部死亡
			for (let i = 0; i < teamPlayers.length; i++) {
				teamPlayers[i].lose(); // 本队所有玩家 lose
			}
			for (const color in players) {
				if (color !== teamColor) {
					const teamPlayers = players[color]; // 其他队伍的玩家
					for (let i = 0; i < teamPlayers.length; i++) {
						teamPlayers[i].win(); // 其他队伍所有玩家 win
					}
				}
			}
		}
	};
	const reciveMessage = function () {
		// arguments 的第一个参数为消息名称
		const message = Array.prototype.shift.call(arguments);
		operations[message].apply(this, arguments);
	};
	return {
		reciveMessage
	}
})();

可以看到,除了中介者本身,没有一个玩家知道其他任何玩家的存在,玩家与玩家之间的耦合关系已经完全解除,某个玩家的任何操作都不需要通知其他玩家,而只需要给中介者发送一个消息,中介者处理完消息之后会把处理结果反馈给其他的玩家对象。我们还可以继续给中介者扩展更多功能,以适应游戏需求的不断变化。

我们来看下测试结果:

// 红队:
var player1 = playerFactory('皮蛋', 'red'),
	player2 = playerFactory('小乖', 'red'),
	player3 = playerFactory('宝宝', 'red'),
	player4 = playerFactory('小强', 'red');
// 蓝队:
var player5 = playerFactory('黑妞', 'blue'),
	player6 = playerFactory('葱头', 'blue'),
	player7 = playerFactory('胖墩', 'blue'),
	player8 = playerFactory('海盗', 'blue');
player1.die();
player2.die();
player3.die();
player4.die();

运行结果如下。

皮蛋 lost
小乖 lost
宝宝 lost
小强 lost
黑妞 won
葱头 won
胖墩 won
海盗 won

假设皮蛋和小乖掉线

player1.remove();
player2.remove();
player3.die();
player4.die();

则结果如下。

宝宝 lost
小强 lost
黑妞 won
葱头 won
胖墩 won
海盗 won

假设皮蛋从红队叛变到蓝队

player1.changeTeam( 'blue' );
player2.die();
player3.die();
player4.die(); 

则结果如下。

小乖 lost
宝宝 lost
小强 lost
黑妞 won
葱头 won
胖墩 won
海盗 won
皮蛋 won

小结

中介者模式是迎合迪米特法则的一种实现。迪米特法则也叫最少知识原则,是指一个对象应该尽可能少地了解另外的对象(类似不和陌生人说话)。如果对象之间的耦合性太高,一个对象发生改变之后,难免会影响到其他的对象,跟“城门失火,殃及池鱼”的道理是一样的。而在中介者模式里,对象之间几乎不知道彼此的存在,它们只能通过中介者对象来互相影响对方。

因此,中介者模式使各个对象之间得以解耦,以中介者和对象之间的一对多关系取代了对象之间的网状多对多关系。各个对象只需关注自身功能的实现,对象之间的交互关系交给了中介者 对象来实现和维护。

不过,中介者模式也存在一些缺点。其中,最大的缺点是系统中会新增一个中介者对象,因为对象之间交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象经常是巨大的。中介者对象自身往往就是一个难以维护的对象。

中介者模式可以非常方便地对模块或者对象进行解耦,但对象之间并非一定需要解耦。在实际项目中,模块或对象之间有一些依赖关系是很正常的。毕竟我们写程序是为了快速完成项目交付生产,而不是堆砌模式和过度设计。关键就在于如何去衡量对象之间的耦合程度。一般来说, 如果对象之间的复杂耦合确实导致调用和维护出现了困难,而且这些耦合度随项目的变化呈指数增长曲线,那我们就可以考虑用中介者模式来重构代码。

到此这篇关于JavaScript设计模式之中介者模式详解的文章就介绍到这了,更多相关JS中介者模式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-08-06

javascript设计模式之中介者模式Mediator

一,总体概要 1,笔者浅谈 我们从日常的生活中打个简单的比方,我们去房屋中介租房,房屋中介人在租房者和房东出租者之间形成一条中介.租房者并不关心他租谁的房.房东出租者也不关心他租给谁.因为有中介的存在,这场交易才变得如此方便. 在软件的开发过程中,势必会碰到这样一种情况,多个类或多个子系统相互交互,而且交互很繁琐,导致每个类都必须知道他需要交互的类,这样它们的耦合会显得异常厉害.牵一发而动全身,后果很严重,大熊很生气!~~~~(>_<)~~~~ 好了,既然问题提出来了,那有请我们这期的主角--

javascript设计模式之中介者模式学习笔记

先来理解这么一个问题,假如我们前端开发接的需求是需求方给我们需求,可能一个前端开发会和多个需求方打交道,所以会保持多个需求方的联系,那么在程序里面就意味着保持多个对象的引用,当程序的规模越大,对象会越来越多,他们之间的关系会越来越复杂,那现在假如现在有一个中介者(假如就是我们的主管)来对接多个需求方的需求,那么需求方只需要把所有的需求给我们主管就可以,主管会依次看我们的工作量来给我们分配任务,这样的话,我们前端开发就不需要和多个业务方联系,我们只需要和我们主管(也就是中介)联系即可,这样的好处就

学习JavaScript设计模式之中介者模式

一.定义 面向对象设计鼓励将行为分布到各个对象中,把对象划分成更小的粒度,有助于增强对象的可复用性.但由于这些细粒度对象之间的联系激增,又可能反过来降低它们的可复用性. 中介者模式的作用就是解除对象与对象之间的紧耦合关系. 二.示例:购买商品 假设我们正在开发一个购买手机的页面,购买流程中,可以选择手机颜色以及输入购买数量,同时页面中可以对应展示输入内容.还有一个按钮动态显示下一步操作(该颜色库存量充足,显示下一步:否则显示库存不足). <div> <span>请选择颜色</

JavaScript设计模式中的桥接和中介者模式

目录 一.桥接设计模式 桥接设计模式在工作中的使用 二.JavaScript中介者模式 生活中的中介者 中介者设计模式案例 业务中的中介者 一.桥接设计模式 桥接设计模式是一种偏向于组合的设计模式,而非继承的设计模式,实现的细节从一个模块推送给另一个具有单独模块的对象 桥接设计模式在开发中常用于事件监控,还有数组的一些方法都能够体现出来桥接设计模式的思想,例如数组方法的forEach方法 桥接设计模式在工作中的使用 有一个很多页面的网站,我们预期是让用户可以选择修改网站的主体,如果给每个页面都创

javascript设计模式 – 中介者模式原理与用法实例分析

本文实例讲述了javascript设计模式 – 中介者模式原理与用法.分享给大家供大家参考,具体如下: 介绍:在前端开发的过程中,组件与组件之间的通讯特别常见,一个组件的change需要引起数个组件的change,这就需要组件与组件之间存在复杂的多对多关系链.如何来减轻维护这些关系的复杂度,让组件和组件之间实现低耦合?这就是我们即将介绍的中介者模式. 定义:用一个中介对象(中介者)来封装一系列的对象交互,中介者使个对象不需要显式的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互.中介

深入理解JavaScript系列(36):设计模式之中介者模式详解

介绍 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 主要内容来自:http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#mediatorpatternjavascript 正文 软件开发中,中介者是一个行为设计模式,通过提供一个统一的接口让系统的不同部分进行通信.一般,如果系统有很多子模块需要直接沟通,

Android编程设计模式之中介者模式详解

本文实例讲述了Android编程设计模式之中介者模式.分享给大家供大家参考,具体如下: 一.介绍 中介者模式(Mediator Pattern)也称为调解者模式或调停者模式,Mediator本身就有调停者和调解者的意思. 在日常生活中调停者或调解者这个角色我们见得比较多的是"和事老",也就是说调解两个有争端的人的角色,举个不恰当的例子,比如爸妈吵架,孩子或者双方父母则会出面劝架或阻止争吵,这里孩子或双方父母则是充当的是调解者的模式. 而对于中介呢?大家平时听得最多的莫过于房产中介了,在

Javascript设计模式之装饰者模式详解篇

一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改变原对象的原本结构的情况下进行功能添加. 2. 装饰对象和原对象具有相同的接口,可以使客户以与原对象相同的方式使用装饰对象. 3. 装饰对象中包含原对象的引用,即装饰对象是真正的原对象经过包装后的对象. 二.Javascript装饰者模式详解: 描述: 装饰者模式中,可以在运行时动态添加附加功能到对

C#设计模式之行为型模式详解

这里列举行为型模式·到此23种就列完了···这里是看着菜鸟教程来实现··,他里边列了25种,其中过滤器模式和空对象模式应该不属于所谓的23种模式 责任链模式:为请求创建一个接收者对象的链,对请求的发送者和接收者进行解耦,大部分用于web中吧.. Task中的continuewith和微软的tpl数据流应该是类似这种模式的实现吧 using System; using System.Collections.Generic; using System.Linq; using System.Text;

php设计模式之简单工厂模式详解

本文以实例形式较为详细的介绍了PHP设计模式的简单工厂模式,对于进行PHP程序设计来说有很好的借鉴作用.具体如下: 一.概念 简单工厂模式 [静态工厂方法模式](Static Factory Method) 是类的创建模式 工厂模式的几种形态: 1.简单工厂模式(Simple Factory)又叫做 静态工厂方法模式(Static Factory Method) 2.工厂方法模式(Factory Method)又叫做 多态性工厂模式(Polymorphic Factory) 3.抽象工厂模式(A

Java设计模式之静态工厂模式详解

本文实例讲述了Java设计模式之静态工厂模式.分享给大家供大家参考,具体如下: 静态工厂模式(static factory)也叫简单工厂模式. 涉及到3个角色:工厂类角色,抽象产品类角色和具体产品类角色. 抽象产品类可以使用接口或者父类来描述产品对象的行为特征. 具体产品类就是某一具体的对象. 静态工厂类有一个静态的方法,含有判断逻辑,决定要创建哪一种具体的产品对象. 其设计模式如下: 抽象产品类  IProduct package org.test.design.sf; public inte

Android编程设计模式之抽象工厂模式详解

本文实例讲述了Android编程设计模式之抽象工厂模式.分享给大家供大家参考,具体如下: 一.介绍 抽象工厂模式(Abstract Factory Pattern),也是创建型设计模式之一.前一节我们已经了解了工厂方法模式,那么这个抽象工厂又是怎么一回事呢?大家联想一下现实生活中的工厂肯定都是具体的,也就是说每个工厂都会生产某一种具体的产品,那么抽象工厂意味着生产出来的产品是不确定的,那这岂不是很奇怪?抽象工厂模式起源于以前对不同操作系统的图形化解决方案,如不同操作系统中的按钮和文本框控件其实现

Android编程设计模式之责任链模式详解

本文实例讲述了Android编程设计模式之责任链模式.分享给大家供大家参考,具体如下: 一.介绍 责任链模式(Iterator Pattern),是行为型设计模式之一.什么是"链"?我们将多个节点首尾相连所构成的模型称为链,比如生活中常见的锁链,就是由一个个圆角长方形的铁环串起来的结构.对于链式结构,每个节点都可以被拆开再连接,因此,链式结构也具有很好的灵活性.将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首端发出,沿着链的路

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

介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止. 也就是说,请求以后,从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者.提交请求的对象并不明确知道哪一个对象将会处理它--也就是该请求有一个隐式的接受者(implicit receiver).根据运行时刻,任一候选者都可以响应相应的请求,候选者的数目是任意

深入理解JavaScript系列(37):设计模式之享元模式详解

介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的 话,就可以大幅度较少需要实例化的类的数量.如果能把那些参数移动到类实例的外面,在方法调用的时候将他们传递进来,就可以通过共享大幅度第减少单个实例 的数目. 那么如果在JavaScript中应用享元模式