標籤:
1. 中介者模式
中介者模式的作用就是用來解除對象與對象之間的緊耦合關係,增加中介者後,所有相關對象都通過中介者來通訊,而不再相互引用
1.1中介者模式的例子
以泡泡堂遊戲為例,先定義一個玩家建構函式,它有三個原型方法
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();
此時藍隊玩家勝利
1.2 用中介者模式改造上述樣本
上述樣本中,每個玩家和其他玩家都是緊耦合在一起,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 }})();
現在除了中介者本身,沒有一個玩家知道其他玩家的存在,玩家與玩家之間的耦合關係已經解除
某個玩家的任何操作不需要通知其他買家,只需要給中介者發送一個訊息
中介者處理完訊息之後,把處理結果反饋給其他玩家
《JavaScript設計模式與開發實踐》讀書筆記之中介者模式