11、中介者模式

1、特点

解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。中介者模式使网状的多对多关系变成了相对简单的一对多关系。

2、demo

泡泡堂游戏

先定义一个玩家构造函数,它有3 个简单的原型方法:Play.prototype.win、Play.prototype.lose。以及表示玩家死亡的Play.prototype.die。因为玩家的数目是2,所以当其中一个玩家死亡的时候游戏便结束, 同时通知它的对手胜利。

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;
};

//红队:
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();
player4.die();
player3.die();

现在我们已经可以随意地为游戏增加玩家或者队伍,但问题是,每个玩家和其他玩家都是紧
紧耦合在一起的。在此段代码中,每个玩家对象都有两个属性,this.partners 和this.enemies,
用来保存其他玩家对象的引用。当每个对象的状态发生改变,比如角色移动、吃到道具或者死亡
时,都必须要显式地遍历通知其他对象。

用中介者模式改造泡泡堂游戏

现在我们开始用中介者模式来改造上面的泡泡堂游戏, 改造后的玩家对象和中介者的关系

首先仍然是定义Player 构造函数和player 对象的原型方法,在player 对象的这些原型方法中,不再负责具体的执行逻辑,而是把操作转交给中介者对象,我们把中介者对象命名为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(color) {
    playerDirector.reciveMessage('changeTeam', this, color); // 给中介者发送消息,玩家换队
};

var playerFactory = function(name, teamColor) {
    var newPlayer = new Player(name, teamColor); // 创造一个新的玩家对象
    playerDirector.reciveMessage('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 = 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
    }
})();

// 红队:
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();

参考文献:《JavaScript设计模式与开发实践》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值