Java设计模式之从[打飞机游戏中的控制器]分析命令(Command)模式

  首先请允许我啰嗦几句。为什么我们在软件设计过程中强调设计模式?为软件增加设计模式确实会增加一定的代码复杂程度,但是它的好处是无穷的。它可以使得软件更加易于扩展而无需改变源代码。“解耦”是设计模式中的一个关键词。例如,对于某个对象obj,在调用obj.method()时,我们希望obj是一个基类或者是一个接口,而不是一个具体的实现类,用这种方式来实现解耦。

  下面进入正题。

  假设我正在做一个打飞机的游戏,我现在正在为飞机编写控制器。飞机的控制器主要可以操作飞机用导弹攻击、炸弹攻击,以及向4个方向移动。我将先给出一段“命令模式”的Java代码,然后再来解释什么叫做命令模式。

  Java代码如下:

interface FighterCommand{
    void execute();
}

//接收者
class Fighter{
    public void missile(){
        System.out.println("用导弹进行攻击!");
    }
    public void bomb(){
        System.out.println("用炸弹进行攻击!");
    }
    public void move(int direction){
        switch (direction){
            case 1:
                System.out.println("向上移动!");
                break;
            case 2:
                System.out.println("向下移动!");
                break;
            case 3:
                System.out.println("向左移动!");
                break;
            case 4:
                System.out.println("向右移动!");
                break;
            default:
                System.out.println("不移动!");
                break;
        }
    }
}

class MissleCommand implements FighterCommand {
    Fighter fighter;
    public MissleCommand(Fighter fighter){
        this.fighter = fighter;
    }
    public void execute(){
        fighter.missile();
    }
}

class BombCommand implements FighterCommand {
    Fighter fighter;
    public BombCommand(Fighter fighter){
        this.fighter = fighter;
    }
    public void execute(){
        fighter.bomb();
    }
}

class MoveCommand implements FighterCommand {
    Fighter fighter;
    int direction;
    public MoveCommand(Fighter fighter, int direction){
        this.fighter = fighter;
        this.direction = direction;
    }
    public void execute(){
        fighter.move(direction);
    }
}

//请求者
class Controller {
    private FighterCommand cmdMissile;
    private FighterCommand cmdBomb;
    private FighterCommand cmdMoveLeft;
    private FighterCommand cmdMoveRight;
    public Controller (FighterCommand missile, FighterCommand bomb, FighterCommand left, FighterCommand right){
        cmdMissile = missile;
        cmdBomb = bomb;
        cmdMoveLeft = left;
        cmdMoveRight = right;
    }
    public void missile(){
        cmdMissile.execute();
    }
    public void bomb(){
        cmdBomb.execute();
    }
    public void moveLeft(){
        cmdMoveLeft.execute();
    }
    public void moveRight(){
        cmdMoveRight.execute();
    }
}

class Command
{
    public static void main(String[] args) {
        Fighter fighter1 = new Fighter();
        FighterCommand cmdMissile = new MissleCommand(fighter1);
        FighterCommand cmdBomb = new BombCommand(fighter1);
        FighterCommand cmdMoveLeft = new MoveCommand(fighter1, 3);
        FighterCommand cmdMoveRight = new MoveCommand(fighter1, 4);
        
        Controller player1 = new Controller (cmdMissile, cmdBomb, cmdMoveLeft, cmdMoveRight);
        player1.bomb();
        player1.missile();
        player1.moveLeft();
        player1.moveRight();
    }
}

  程序运行结果如下:

用炸弹进行攻击!

用导弹进行攻击!

向左移动!

向右移动

  请仔细体会上面代码的用意。命令模式主要由命令的接收者(Fighter)、命令的行为(FighterCommand接口)以及命令的请求者(Controller)组成。它的意图是将请求封装为一个对象(FighterCommand的派生类),从而使得你可以用不同的请求对客户进行参数化;对请求排队或者记录请求日志、支持撤销等操作。

  如上面的代码,我们把飞机的行为(左、右移动;发射导弹;投放炸弹)分别卸载了3个不同的类中,而这3个类中都包含对战斗机Fighter的引用,战斗机作为动作的接收类,可以实现这些行为。我们把这些动作都聚合在了Controller类中,由Controller类发出请求信息,请求经过了FighterCommand,最终由Fighter类接收,并且可以知道应该做出什么样的行为。

  接下来疑惑就出现了:为什么要煞费苦心地建立一个Controller类,为什么不直接调用fighter1.bomb(); fighter1.missile()等方法呢?原因是两个字——解耦。如本文一开始所说,当调用obj.method()时,我们希望obj是一个基类对象或者是一个接口对象,因为这样它可以适用于一类方法,而不是某一个特定类型的方法。在本例中使用命令模式的好处就在于,我们将Fighter的行为与其本身的对象解耦。假设某一天,我们希望Fighter的bomb()方法发生一些变化,如在放炸弹之前先调用missile方法,若不用命令模式,我们需要在所有调用Fighter.bomb()方法之前调用一次Fighter.missile(),这是何等的麻烦!如果用了命令模式,我们可以建立一个新的FighterCommand,将execute方法写为先调用missile()再调用bomb,最后修改Controller类传入的构造参数即可。设计模式的用途在此体现:让软件更加易于扩展。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值