zoukankan      html  css  js  c++  java
  • 《JavaScript设计模式与开发实践》读书笔记之中介者模式

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

    现在除了中介者本身,没有一个玩家知道其他玩家的存在,玩家与玩家之间的耦合关系已经解除

    某个玩家的任何操作不需要通知其他买家,只需要给中介者发送一个消息

    中介者处理完消息之后,把处理结果反馈给其他玩家

  • 相关阅读:
    【Jenkins】插件更改国内源
    【Jenkins】参数化引用
    【selenium】各种exception
    利用浏览器的console篡改cookie
    【python】django 分页器 Paginator 基础操作
    centos7 安装php7遇到的问题
    归并排序(自顶向下、原地归并)
    希尔排序
    插入排序
    选择排序
  • 原文地址:https://www.cnblogs.com/GongQi/p/4681630.html
Copyright © 2011-2022 走看看