首页 > 代码库 > JavaScript中介者模式

JavaScript中介者模式

      中介者模式是迎合迪米特法则的一种实现。迪米特法则也叫最少知识原则,是指一个对象应该尽可能少地了解另一个对象。如果对象间的耦合性太高,一个对象发生改变后,难免会影响到其他的对象。在中介者模式里,对象间几乎不知道彼此的存在,它们只能通过中介者对象来互相影响。因此,中介者模式使各个对象得以解耦,以中介者和对象之间的一对多的关系取代了对象间的多对多的网状关系。各个对象只需关注自身功能的实现,对象之间的交互关系就交给中介者对象来实现和维护。
      下面是一段使用中介者模式改良后的游戏的代码:

      function Player( name, teamColor ){
            this.name = name; // 角色名字
            this.teamColor = teamColor; // 队伍颜色
            this.state = ‘alive‘; // 玩家生存状态
      }

      Player.prototype.win = function(){
            console.log( this.name + ‘ win‘ );
      }

      Player.prototype.lose = function(){
            console.log( this.name + ‘ lose‘ );
      }

/***************玩家死亡**************/
      Player.prototype.die = function(){
            this.state = ‘dead‘;
            playerDirector.ReceiveMessage( ‘playerDead‘, this ); // 给中介者发消息,玩家死亡
      }

/***************移除玩家**************/
      Player.prototype.remove = function(){
            playerDirector.ReceiveMessage( ‘removePlayer‘, this ); // 给中介者发消息,移除一个玩家
      }

/***************玩家换队**************/
      Player.prototype.changeTeam = function(){
            playerDirector.ReceiveMessage( ‘changeTeam‘, this, color ); // 给中介者发消息,玩家换队
      }

 

      var playerFactory = function( name, teamColor ){

            var newPlayer = new Player( name, teamColor );     // 创建一个新的玩家对象

            playerDirector.ReceiveMessage( ‘addPlayer‘, newPlayer );   // 给中介者发送消息,新增玩家

            return newPlayer;

      }

 

     //中介者
      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 = teamPlayrs[ i++ ]; ){
                        if( player.state != ‘dead‘ ){
                              all_dead = false;
                              break;
                        }
                  }

                  if( all_dead ){
                        for( var i = 0, player; player = teamPlayrs[ i++ ]; ){
                              player.lose(); // 本队所有玩家输
                        }
                        for( var color in players ){
                              if( color !== teamColor ){
                                    var teamPlayrs = players[ color ]; // 其他队伍的玩家
                                    for( var i = 0, player; player = teamPlayrs[ i++ ]; ){
                                          player.win(); // 其他队伍所有玩家赢
                                    }
                               }
                         }
                   }   

           }

           /***************对外接口,接受各个玩家的消息**************/
            var ReceiveMessage = function(){
                  var message = Array.prototype.shift.call( arguments ); // arguments的第一个参数为消息名称
                  operations[ message ].apply( this, arguments );
            }


            return {
                  ReceiveMessage: 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();
      // 输出结果:lost -->> 皮蛋、小乖、宝宝、小强 ; win -->> 黑妞、葱头、胖墩、海盗

 

      不过,中介者模式也存在一些缺点。其中,最大的缺点是系统中会新增一个中介者对象,这是一个很大的对象,往往它就是一个很难维护的对象。所以在选择这个模式的时候,要考虑清楚利与弊。

 

JavaScript中介者模式