js中介者模式总结

内容来自《JavaScript设计模式与开发实践》一书,本人不才,也是阅读这本书第二遍的时候才理解了这种模式的好处😂

现实中的中介者模式的场景:

博彩公司

打麻将的人经常遇到这样的问题,打了几局之后开始计算钱,A 自摸了两把,B 杠了三次,C 点炮一次给 D,谁应该给谁多少钱已经很难计算清楚,而这还是在只有 4 个人参与的情况下。

在世界杯期间购买足球彩票,如果没有博彩公司作为中介,上千万的人一起计算赔率和输赢绝对是不可能实现的事情。有了博彩公司作为中介,每个人只需和博彩公司发生关联,博彩公司会根据所有人的投注情况计算好赔率,彩民们赢了钱就从博彩公司拿,输了钱就交给博彩公司。

所以下面以一个队伍间对战的游戏来举例,首先构思一下

这里重点提一下中介者,他其实相当于一个控制中心,不管哪支队伍的哪个玩家发生了任何状态的改变(比如:换队、死亡、移除玩家)都是把这个消息发送给控制中心,由控制中心来处理,下面的例子中的 playerDirector 相当于是这个控制中心。

1.Player:玩家姓名、队伍颜色(蓝、红)、生存状态(alive、dead)
  实现原型方法:换队、移除玩家、玩家死亡、玩家胜利、玩家失败
  
2.playerFactory:制造玩家,并将其填入到 中介者 的玩家列表里
  
3.playerDirector:中介者:暴露 receiveMessage 接口给外部使用
  需要有属性:players(存放不同队伍的所有玩家)、operations(存放中介者内部的方法)
  暴露一个receiveMessage方法供外部使用,通过这个接口来调用 playerDirector 内部的方法
  需要实现方法:增加玩家、换队、移除玩家、玩家死亡
    
  PS:这里注意一下玩家死亡的业务逻辑:如果某个玩家死亡,首先判断他所在的队伍玩家是否全部死亡,如果全部死亡,那么这支队伍的所有玩家都输了,并且除了这支队伍以外的其他队伍的所有玩家都获得胜利
/*
  玩家类
*/
function Player(name, teamColor) {
  this.name = name;
  this.teamColor = teamColor;
  this.state = 'alive';
}

Player.prototype.changeTeam = function( newTeamColor ) {
  playerDirector.receiveMessage('changeTeam', this, newTeamColor);
}

Player.prototype.remove = function() {
  playerDirector.receiveMessage('removePlayer', this);
}

Player.prototype.die = function() {
  this.state = 'dead';
  playerDirector.receiveMessage('playerDead', this);
}

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

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

/*
  PlayerFactory:制造玩家,并将其填入到 中介者 的玩家列表里
*/
var playerFactory = function(name, teamColor) {
  var player = new Player(name, teamColor);
  playerDirector.receiveMessage('addPlayer', player);
  return player;
}

/*
  中介者:暴露 receiveMessage 接口给外部使用
    需要有属性:players、operations
    需要实现方法:增加玩家、换队、移除玩家、玩家死亡、玩家胜利、玩家失败
*/
var playerDirector = (function() {
  var players = {},
      operations = {};
  
  operations.addPlayer = function(player) {
    let teamColor = player.teamColor;

    if (!players[ teamColor ] || players[ teamColor ].length === 0) {
      players[ teamColor ] = [];
    }
    players[ teamColor ].push( player );
  };

  operations.removePlayer = function(player) {
    let teamColor = player.teamColor;

    if (!players[ teamColor ] || players[ teamColor ].length === 0) {
      players[ teamColor ] = [];
    }

    let teamColorPlayers = players[ teamColor ];
    for (let i = 0, curr; curr = teamColorPlayers[i++];) {
      if (curr === player) {
        teamColorPlayers.splice(i, 1);
        break;
      }
    }
  };

  operations.changeTeam = function(player, newTeamColor) {
    operations.removePlayer(player);
    player.teamColor = newTeamColor;
    operations.addPlayer(player);
  };

  operations.playerDead = function(player) {
    let teamColor = player.teamColor;

    let allDead = true,
        teamColorPlayers = players[ teamColor ] || [];
    for (let i = 0, curr; curr = teamColorPlayers[i++];) {
      if (curr.state !== 'dead') {
        allDead = false;
        break;
      }
    }

    if (allDead === true) {
      for (let i = 0, curr; curr = teamColorPlayers[i++];) {
        curr.lose();
      }

      for (let color in players) {
        if (color !== teamColor) {
          let colorPlayers = players[ color ];
          for (let i = 0, curr; curr = colorPlayers[i++];) {
            curr.win();
          }
        }
      }
    }
  };

  var receiveMessage = function() {
    let act = Array.prototype.shift.call( arguments );
    operations[act].apply(this, arguments);
  };

  return {
    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();

最终输出

皮蛋 lose..
小乖 lose..
宝宝 lose..
小强 lose..
黑妞 win!
葱头 win!
胖墩 win!
海盗 win!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值