解除对象与对象之间的紧耦合关系。
生活中场景:机场指挥塔。
- 泡泡堂游戏
- 定义数组保存所有的玩家
var players = [];
- 构造函数,创建玩家,增加属性。
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(){ // 玩家死亡
var all_dead = true;
this.state = 'dead'; // 设置玩家状态为死亡
for ( var i = 0, partner; partner = this.partners[ i++ ]; ){ // 遍历队友列表
if ( partner.state !== 'dead' ){ // 如果还有一个队友没有死亡,则游戏还未失败
all_dead = false;
break;
}
}
if ( all_dead === true ){ // 如果队友全部死亡
this.lose(); // 通知自己游戏失败
for ( var i = 0, partner; partner = this.partners[ i++ ]; ){ // 通知所有队友玩家游戏失败
partner.lose();
}
for ( var i = 0, enemy; enemy = this.enemies[ i++ ]; ){ // 通知所有敌人游戏胜利
enemy.win();
}
}
};
- 创建一个新玩家后,要找到队友和敌人,所以定义一个工厂来创建玩家。
var playerFactory = function( name, teamColor ){
var newPlayer = new Player( name, teamColor ); // 创建新玩家
for ( var i = 0, player; player = players[ i++ ]; ){ // 通知所有的玩家,有新角色加入
if ( player.teamColor === newPlayer.teamColor ){ // 如果是同一队的玩家
player.partners.push( newPlayer ); // 相互添加到队友列表
newPlayer.partners.push( player );
}else{
player.enemies.push( newPlayer ); // 相互添加到敌人列表
newPlayer.enemies.push( player );
}
}
players.push( newPlayer );
return newPlayer;
};
上述缺点:主要体现在第5步,每创建一个玩家,都要遍历所有的玩家,然后相互添加为队友或敌人。
每个玩家紧耦合在一起。并且不容易增加新功能,比如玩家换队。
- 使用中介者模式改造
- 构造函数,不再执行具体逻辑。
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 ); // 给中介者发送消息,玩家换队
};
- 工厂函数作用和之前一样。
var playerFactory = function( name, teamColor ){
var newPlayer = new Player( name, teamColor );
playerDirector.ReciveMessage( 'addPlayer', this );
return newPlayer;
};
- 定义中介者
playerDirector, 从上面可以看出,需要暴露接口ReceiveMessage
var playerDirector= ( function(){
var players = {}, // 保存所有玩家
operations = {}; // 中介者可以执行的操作
operations.addPlayer = function( player ){
// ...
};
operations.removePlayer = function( player ){
//...
};
operations.changeTeam = function( player, newTeamColor ){
// ..
};
operations.playerDead = function( player ){
// ...
};
var reciveMessage = function(){
var message = Array.prototype.shift.call( arguments ); // arguments 的第一个参数为消息名称
operations[ message ].apply( this, arguments );
};
return {
reciveMessage: reciveMessage
}
})();
优点:玩家之间耦合解除。某个玩家的操作,只需通知中介者,中介者处理后再反馈给其他玩家。
- 购买商品例子