内容来自《JavaScript设计模式与开发实践》一书,本人不才,也是阅读这本书第二遍的时候才理解了这种模式的好处😂
现实中的中介者模式的场景:
博彩公司
打麻将的人经常遇到这样的问题,打了几局之后开始计算钱,A 自摸了两把,B 杠了三次,C 点炮一次给 D,谁应该给谁多少钱已经很难计算清楚,而这还是在只有 4 个人参与的情况下。
在世界杯期间购买足球彩票,如果没有博彩公司作为中介,上千万的人一起计算赔率和输赢绝对是不可能实现的事情。有了博彩公司作为中介,每个人只需和博彩公司发生关联,博彩公司会根据所有人的投注情况计算好赔率,彩民们赢了钱就从博彩公司拿,输了钱就交给博彩公司。
所以下面以一个队伍间对战的游戏来举例,首先构思一下
这里重点提一下中介者,他其实相当于一个控制中心,不管哪支队伍的哪个玩家发生了任何状态的改变(比如:换队、死亡、移除玩家)都是把这个消息发送给控制中心,由控制中心来处理,下面的例子中的 playerDirector 相当于是这个控制中心。
1.Player:玩家姓名、队伍颜色(蓝、红)、生存状态(alive、dead)
实现原型方法:换队、移除玩家、玩家死亡、玩家胜利、玩家失败
2.playerFactory:制造玩家,并将其填入到 中介者 的玩家列表里
3.playerDirector:中介者:暴露 receiveMessage 接口给外部使用
需要有属性:players(存放不同队伍的所有玩家)、operations(存放中介者内部的方法)
暴露一个receiveMessage方法供外部使用,通过这个接口来调用 playerDirector 内部的方法
需要实现方法:增加玩家、换队、移除玩家、玩家死亡
PS:这里注意一下玩家死亡的业务逻辑:如果某个玩家死亡,首先判断他所在的队伍玩家是否全部死亡,如果全部死亡,那么这支队伍的所有玩家都输了,并且除了这支队伍以外的其他队伍的所有玩家都获得胜利
/*
玩家类
*/
function Player(name, teamColor) {
this.name = name;
this.teamColor = teamColor;
this.state = 'alive';
}
Player.prototype.changeTeam = function( newTeamColor ) {
playerDirector.receiveMessage('changeTeam', this, newTeamColor);
}
Player.prototype.remove = function() {
playerDirector.receiveMessage('removePlayer', this);
}
Player.prototype.die = function() {
this.state = 'dead';
playerDirector.receiveMessage('playerDead', this);
}
Player.prototype.win = function() {
console.log( this.name + ' win!' );
}
Player.prototype.lose = function() {
console.log( this.name + ' lose..' );
}
/*
PlayerFactory:制造玩家,并将其填入到 中介者 的玩家列表里
*/
var playerFactory = function(name, teamColor) {
var player = new Player(name, teamColor);
playerDirector.receiveMessage('addPlayer', player);
return player;
}
/*
中介者:暴露 receiveMessage 接口给外部使用
需要有属性:players、operations
需要实现方法:增加玩家、换队、移除玩家、玩家死亡、玩家胜利、玩家失败
*/
var playerDirector = (function() {
var players = {},
operations = {};
operations.addPlayer = function(player) {
let teamColor = player.teamColor;
if (!players[ teamColor ] || players[ teamColor ].length === 0) {
players[ teamColor ] = [];
}
players[ teamColor ].push( player );
};
operations.removePlayer = function(player) {
let teamColor = player.teamColor;
if (!players[ teamColor ] || players[ teamColor ].length === 0) {
players[ teamColor ] = [];
}
let teamColorPlayers = players[ teamColor ];
for (let i = 0, curr; curr = teamColorPlayers[i++];) {
if (curr === player) {
teamColorPlayers.splice(i, 1);
break;
}
}
};
operations.changeTeam = function(player, newTeamColor) {
operations.removePlayer(player);
player.teamColor = newTeamColor;
operations.addPlayer(player);
};
operations.playerDead = function(player) {
let teamColor = player.teamColor;
let allDead = true,
teamColorPlayers = players[ teamColor ] || [];
for (let i = 0, curr; curr = teamColorPlayers[i++];) {
if (curr.state !== 'dead') {
allDead = false;
break;
}
}
if (allDead === true) {
for (let i = 0, curr; curr = teamColorPlayers[i++];) {
curr.lose();
}
for (let color in players) {
if (color !== teamColor) {
let colorPlayers = players[ color ];
for (let i = 0, curr; curr = colorPlayers[i++];) {
curr.win();
}
}
}
}
};
var receiveMessage = function() {
let act = Array.prototype.shift.call( arguments );
operations[act].apply(this, arguments);
};
return {
receiveMessage
}
})();
// 红队:
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();
最终输出
皮蛋 lose..
小乖 lose..
宝宝 lose..
小强 lose..
黑妞 win!
葱头 win!
胖墩 win!
海盗 win!