中介者模式的作用就是用来解除对象与对象之间的紧耦合关系,增加中介者后,所有相关对象都通过中介者来通信,而不再相互引用
以泡泡堂游戏为例,先定义一个玩家构造函数,它有三个原型方法
Player.prototype.win,Player.prototype.lose,Player.prototype.die
当只有两个玩家时,一个玩家死亡时游戏结束,同时通知他的对手胜利
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+'lose'); }; Player.prototype.die=function(){ console.log(this.name+'die'); };
接下来创建两个玩家
var player1=new Player('玩家1'); var player2=new Player('玩家2'); //设置敌人 player1.enemy=player2; player2.enemy=player1; //玩家1死亡时,调用自己的die方法完成一局游戏 player1.die();
当玩家增加时,每个玩家有了自己的队友和若干敌人
定义一个数组players保存所有的玩家,创建玩家之后,循环players来给每个玩家设置敌人和队友
var 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(){ 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; };
用这段代码来创建8个玩家,分属红蓝两队
var player1=playerFactory('p1','red'); var player2=playerFactory('p2','red'); var player3=playerFactory('p3','red'); var player4=playerFactory('p4','red'); var player5=playerFactory('p5','blue'); var player6=playerFactory('p6','blue'); var player7=playerFactory('p7','blue'); var player8=playerFactory('p8','blue');
让红队全部死亡
player1.die();
player2.die();
player3.die();
player4.die();
此时蓝队玩家胜利
上述示例中,每个玩家和其他玩家都是紧耦合在一起,partners,enemies保存着其他玩家对象的引用。当对象状态改变,如死亡时,必须显示遍历通知其他玩家
首先仍然是定义Player构造函数和player对象的原型方法
function Player(name,teamColor){ this.name=name; this.teamColor=teamColor; this.state=state; }; 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.ReceiveMessage('playerDead',this); }; //移除玩家 Player.prototype.remove=function(){ playerDirector.ReceiveMessage('removePlayer',this); }; //玩家换队 Player.prototype.changeTeam=function(color){ playerDirector.ReceiveMessage('changeTeam',this,color); };
改写创建玩家对象的工厂函数
var playerFactory=function(name,teamColor){ var newPlayer=new Player(name,teamColor); playerDirector.ReceiveMessage('addPlayer',newPlayer); return newPlayer; };
playerDirector开放一个对外暴露的接口ReceiveMessage,负责接收player对象发送的消息,
而player对象发送的时候,总是把自身this作为参数发送给playDirector,以便playerDirector识别消息来自于哪个玩家对象
var playerDirector=(function(){ var players={},//保存所有玩家 operations={};//中介者可以执行的操作 //新增一个玩家 operations.addPlayer=function(player){ var teamColor=player.teamColor //如果该颜色的玩家还没有成立队伍,则新成立一个队伍 players[teamColor]=players[teamColor]||[]; players[teamColor].push(player);//添加玩家进队伍 }; //移除一个玩家 operations.removePlayer=function(player){ var teamColor=player.teamColor, teamPlayers=players[teamColor]||[];//该队伍所有成员 for(var i=teamPlayers.length-1;i>=0;i--){ if(teamPlayers[i]===player{ teamPlayers.splice(i,1); } } }; //玩家换队 operations.changeTeam=function(player,newTeamColor){ operations.removePlayer(player); player.teamColor=newTeamColor; operations.addPlayer(player); } //玩家死亡 operations.playerDead=function(player){ var teamColor=player.teamColor, teamPlayers=players[teamColor]; var all_dead=true; for(var i=0,player;player=teamPlayers[i++];){ if(player.state!='dead'){ all_dead=false; break; } } //如果全部死亡 if(all_dead===true){ for(var i=0,player;player=teamPlayers[i++];){ player.lose(); } for(var color in players){ if(color !== teamColor){ var teamPlayers=players[color];//对手玩家 for(var i=0,player;player=teamPlayers[i++];){ player.win(); } } } } } var ReceiveMessage=function(){ var message=Array.prototype.shift.call(arguments); operations[message].apply(this,arguments); }; return{ ReceiveMessage:ReceiveMessage } })();
现在除了中介者本身,没有一个玩家知道其他玩家的存在,玩家与玩家之间的耦合关系已经解除
某个玩家的任何操作不需要通知其他买家,只需要给中介者发送一个消息
中介者处理完消息之后,把处理结果反馈给其他玩家