>[success] # 利用中介者模式去优化刚才代码思路 ~~~ 1.两种解决方案: 1.1. 利用发布—订阅模式。将 'playerDirector' 实现为'订阅者',各 'player' 作为'发布者',一旦 player 的'状态发生改变',便推送消息给 'playerDirector','playerDirector' 处理消息后将反馈发送给其他'player'。 1.2.在 'playerDirector' 中开放一些接收消息的接口,各 'player' 可以直接调用该接口来给'playerDirector' 发送消息,'player' 只需传递一个参数给 'playerDirector',这个参数的目的是使 'playerDirector' 可以识别 发送者。同样,playerDirector 接收到消息之后会将处理结果反馈给其他 player。 ~~~ >[info] ## 书中采用第二种模式来写 ~~~ 1.根据第二种模式来进行分析,首先'playerDirector' 就变成了一个中转站,变成'player' 玩家实例和整个队伍 根据玩家动作产生的队伍结果导向的桥梁,在上了例子中,玩家死亡就会触发队伍信息,让整个玩家和队伍 变得紧凑起来,现在做法就是让这种紧凑消除,所有关于队伍的出来都交个了'playerDirector' 2.为了让所有玩家可以和自己队伍进行关联保证互相匹配,'playerDirector' 对应也要保存所有玩家的实例对象 ~~~ >[danger] ##### 编写第一部分玩家类 ~~~ 1.上面说到'playerDirector':在 'playerDirector' 中开放一些接收消息的接口,各 'player' 可以直接调用该接口来 给'playerDirector'发送消息,这里的'die' ,'remove ','changeTeam' 这三个方法都会去调用对应'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 () { playerDirector.reciveMessage( 'changeTeam', this, color ); // 给中介者发送消息,玩家换队 } ~~~ >[danger] ##### playerDirector 处理的中介者 ~~~ var playerDirector = ( function () { var players = {} ,// 保存所有玩家 operations = {} // 中介者可以执行的操作 // 新增玩家 operations.addPlayer = function (player) { var teamColor = player.teamColor // 获取玩家颜色 players[teamColor] = players[teamColor] || [] // 存在则获取现在该队伍的玩家数组,不存在就新建一个 players[teamColor].push(player) // 将玩家对象放进players 对象中 } // 移除玩家 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(); // 本队所有玩家 lose } for ( var color in players ){ if ( color !== teamColor ){ var teamPlayers = players[ color ]; // 其他队伍的玩家 for ( var i = 0, player; player = teamPlayers[ i++ ]; ){ player.win(); // 其他队伍所有玩家 win } } } } }; var reciveMessage = function(){ var message = Array.prototype.shift.call( arguments ); // arguments 的第一个参数为消息名称 operations[ message ].apply( this, arguments ); }; return { reciveMessage: reciveMessage } } )() ~~~ >[danger] ##### 将玩家分队的工厂函数 ~~~ // 创建队伍的工厂 var playerFactory = function( name, teamColor ){ var newPlayer = new Player( name, teamColor ); // 创造一个新的玩家对象 playerDirector.reciveMessage( 'addPlayer', newPlayer ); // 给中介者发送消息,新增玩家 return newPlayer; }; ~~~ >[danger] ##### 使用 ~~~ // 红队: 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(); ~~~