命令模式 Command Pattern

命令模式 Command Pattern

Command Pattern的目的在于分离命令的发出者和命令的执行者。就好比在饭店吃饭,作为客户(命令的发出者),你无需直接跟厨师说明要点什么菜,只要把菜单给服务员就行了,而服务员并不负责烧菜,只要把菜单交给厨师(执行者)即可,厨师会根据菜单做菜了。这两者被分离了。

 

下面来实现这个点菜的过程:我们要点两个菜,burgermalt。最简单的实现如下:

package javaapplication29;

 

public class Main {

    public static void main(String[] args) {

        Cook cook = new Cook();

        cook.burger();

        cook.malt();

    }

}

 

class Cook {

    void burger() {

        System.out.println("burger maked");

    }

    void malt() {

        System.out.println("malt maked");

    }

}

 

这里有个问题:我们要点什么菜,是写在主函数里的。如果要点的菜有所改变,比如第二个人要点菜,点其他菜,那么主函数里的代码就要重写。这里就出现了所谓的“变化没有被封装”的问题。这里的代码实现过程就好比顾客直接跟厨师说要吃什么菜一样。

 

这里我们引入“菜单”,所谓菜单的作用在于:把变化的“点什么菜”封装到菜单这个对象里面去。实际上就是把主函数中变化的部分封装到一个类中去了。

package javaapplication29;

 

public class Main {

    public static void main(String[] args) {

        Cook cook = new Cook();

        Manu1 manu1 = new Manu1(cook);

        manu1.orderup();

    }

}

 

class Cook {

    void burger() {

        System.out.println("burger maked");

    }

    void malt() {

        System.out.println("malt maked");

    }

}

 

class Manu1 {

    Cook cook;

    public Manu1(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

        cook.malt();

    }

}

 

 

如果有第二个菜单,我们就再写第二个类Manu2出来:

package javaapplication29;

 

public class Main {

    public static void main(String[] args) {

        Cook cook = new Cook();

        Manu1 manu1 = new Manu1(cook);

        manu1.orderup();

       

        Manu2 manu2=new Manu2(cook);

        manu2.orderup();

    }

}

 

class Cook {

    void burger() {

        System.out.println("burger maked");

    }

    void malt() {

        System.out.println("malt maked");

    }

}

 

class Manu1 {

    Cook cook;

    public Manu1(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

        cook.malt();

    }

}

 

class Manu2 {

    Cook cook;

    public Manu2(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

    }

}

          

这里我们发现Manu1Manu2两个类形式几乎相通,只是orderup()函数内执行的东西不一样。在主函数中,要执行第二个菜单还得重新生成一个对象,Manu2 manu2=new Manu2(cook);  而不能直接切换,manu1=new Manu2(cook);   这很不爽,由此很容易想到用一个父类,让Manu1Manu2继承之,如下:

 

package javaapplication29;

 

public class Main {

    public static void main(String[] args) {

        Cook cook = new Cook();

        Manu manu = new Manu1(cook);

        manu.orderup();

 

        manu = new Manu2(cook);

        manu.orderup();

    }

}

 

class Cook {

    void burger() {

        System.out.println("burger maked");

    }

    void malt() {

        System.out.println("malt maked");

    }

}

 

abstract class Manu {

    abstract public void orderup();

}

 

class Manu1 extends Manu {

    Cook cook;

    public Manu1(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

        cook.malt();

    }

}

 

class Manu2 extends Manu {

    Cook cook;

    public Manu2(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

    }

}

 

这个实际上变成工厂模式了。我们看到主函数中:

Manu manu = new Manu1(cook);

manu.orderup();

这里,命令的发出是通过菜单的orderup方法发出的。可实际中,菜单是不能发命令的,而是客户通过服务员发命令的。我们需要一个Waitress这个对象来装载各种菜单,并对厨师发出点菜的命令(通过调用Manuorderup方法)。如下:

 

package javaapplication29;

 

public class Main {

    public static void main(String[] args) {

        Cook cook = new Cook();

        Waitress waitress = new Waitress();

 

        Manu manu = new Manu1(cook);

        waitress.setManu(manu);

        waitress.callCook();

 

        manu = new Manu2(cook);

        waitress.setManu(manu);

        waitress.callCook();

    }

}

 

class Cook {

    void burger() {

        System.out.println("burger maked");

    }

    void malt() {

        System.out.println("malt maked");

    }

}

 

abstract class Manu {

    abstract public void orderup();

}

 

class Manu1 extends Manu {

    Cook cook;

    public Manu1(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

        cook.malt();

    }

}

 

class Manu2 extends Manu {

    Cook cook;

    public Manu2(Cook cook) {

        this.cook = cook;

    }

    public void orderup() {

        cook.burger();

    }

}

 

class Waitress {

    Manu manu;

    public void setManu(Manu manu) {

        this.manu = manu;

    }

    public void callCook() {

        manu.orderup();

    }

}

命令模式 Command Pattern_第1张图片

在这个程序里,我们发现其实Waitress在主程序中只知道要callCook()

waitress.callCook();

而她并不知道callCook()在具体执行什么,因为Waitress类中的manu是一个抽象类的对象,而callCook()方法中的manu.orderup() 是抽象方法,鬼知道它的具体实现是什么。

 

这就是Command Pattern的目的:把命令封装成对象(Manu1Manu2),让调用命令的人(Waitress)装载该对象(setManu),随时可以发出该命令(callCook)。而调用命令的人,并不知道该命令的具体执行过程。

 

这有点类似于给工厂模式中的抽象工厂添加了一个装载器。值得注意的是,在工厂模式中,顶层的抽象工厂一般是抽象类,而在命令模式中,顶层的一般都是接口。其实到底用抽象类还是接口并不重要!因为在某种程度上,他们都是Interface。到底用哪个,根据需要使用,毕竟可以实现多接口而不能继承多个抽象类。Command Pattern的关键不在于这里,而在于装载器和工厂模式的结合。

 

head first design pattern》上要实现一个远程控制器,思路跟上面一样。代码如下所示:

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        Command command = new LightOnCommand(light);

        RemoteControl rc = new RemoteControl();

        rc.setControl(command);

        rc.ButtonDown();

 

        GarageDoor garageDoor = new GarageDoor();

        command = new GarageDoorOpenCommand(garageDoor);

        rc.setControl(command);

        rc.ButtonDown();

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

}

 

interface Command {

    public void execute();

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command command;

    public void setControl(Command command) {

        this.command = command;

    }

    public void ButtonDown() {

        command.execute();

    }

}

 

 

以上设计出的远程控制器只有一个slot,对应一个按钮。现在如果要实现7slot,每个slot对应一个“打开”按钮,则需要把RemoteControl这个类改动一下:

 

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command command = new LightOnCommand(light);

        rc.setControl(0, command);

 

        command = new GarageDoorOpenCommand(garageDoor);

        rc.setControl(1, command);

 

        rc.buttonDown(0);

        rc.buttonDown(1);

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

}

 

interface Command {

    public void execute();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

Command noCommand = new noCommand();

 

    public RemoteControl() {

        onCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand; //初始化7个槽对应的按钮指令为空

        }

    }

    public void setControl(int slot, Command command) {

        onCommands[slot] = command;

    }

    public void buttonDown(int slot) {

        onCommands[slot].execute();

    }

}

 

对比之前的只有一个slot的程序,RemoteControl类添加了一个初始化作用的构造函数,并在每个方法的参数表里添加了slot参数。

 

如果想要有7slot,每个slot都对应“开”、“关”两个按钮,则同理,讲RemoteControl中的参数再各增加一个即可,如下:

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command onCommand = new LightOnCommand(light);

        Command offCommand = new LightOffCommand(light);

        rc.setControl(0, onCommand, offCommand);

 

        onCommand = new GarageDoorOpenCommand(garageDoor);

        offCommand = new GarageDoorCloseCommand(garageDoor);

        rc.setControl(1, onCommand, offCommand);

 

        rc.onButtonDown(0);

        rc.offButtonDown(1);

        rc.offButtonDown(0);

        rc.onButtonDown(1);

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

interface Command {

    public void execute();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

}

 

class RemoteControl {

    Command[] onCommands;

Command[] offCommands;

Command noCommand = new noCommand();

 

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

    }

}

 

 

如何给上面的程序添加一个undo按钮呢,就是撤销上一次的操作。

(1)       我们要给Command接口以及它的所有实现体(LightOnCommand, GarageCloseCommand等)添加undo()方法,undo执行的内容就是和execute()执行相反的即可。

(2)       我们还在RemoteControl类中,想办法记录最后一次执行的是哪个XXXCommand

 

实现如下:

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command onCommand = new LightOnCommand(light);

        Command offCommand = new LightOffCommand(light);

        rc.setControl(0, onCommand, offCommand);

 

        onCommand = new GarageDoorOpenCommand(garageDoor);

        offCommand = new GarageDoorCloseCommand(garageDoor);

        rc.setControl(1, onCommand, offCommand);

 

        rc.onButtonDown(0);

        rc.undoButtonDown();

        rc.offButtonDown(1);

        rc.offButtonDown(0);

        rc.onButtonDown(1);

        rc.undoButtonDown();

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

interface Command {

    public void execute();

    public void undo();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

    public void undo() {

        System.out.println("no command here.");

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

    public void undo() {

        light.off();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

    public void undo() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

    public void undo() {

        garageDoor.close();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

    public void undo() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

    Command[] offCommands;

    Command noCommand = new noCommand();

    Command lastCommand;

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

        lastCommand = onCommands[slot];

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

        lastCommand = offCommands[slot];

    }

    public void undoButtonDown() {

        lastCommand.undo();

    }

}

 

电器的功能可能不止“开”和“关”,比如电风扇,有换挡功能。对于电风扇的HighMediumLow三个档位,每个要写一个单独的FanXXXCommand类。对每个档位做undo的时候,不能直接简单的取反,要找到上一次的档位才行。

 

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command onCommand = new LightOnCommand(light);

        Command offCommand = new LightOffCommand(light);

        rc.setControl(0, onCommand, offCommand);

 

        onCommand = new GarageDoorOpenCommand(garageDoor);

        offCommand = new GarageDoorCloseCommand(garageDoor);

        rc.setControl(1, onCommand, offCommand);

 

        rc.onButtonDown(0);

        rc.undoButtonDown();

        rc.offButtonDown(1);

        rc.offButtonDown(0);

        rc.onButtonDown(1);

        rc.undoButtonDown();

 

        Fan fan = new Fan();

        onCommand = new FanHighCommand(fan);

        offCommand = new FanOffCommand(fan);

        rc.setControl(2, onCommand, offCommand);

        rc.onButtonDown(2);

        rc.offButtonDown(2);

        rc.undoButtonDown();

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

class Fan {

    public final int HIGH = 3;

    public final int MEDIUM = 2;

    public final int LOW = 1;

    public final int OFF = 0;

    public int speed = 0;

    public void high() {

        speed = HIGH;

        System.out.println("Fan's speed is " + speed);

    }

    public void low() {

        speed = LOW;

        System.out.println("Fan's speed is " + speed);

    }

    public void medium() {

        speed = MEDIUM;

        System.out.println("Fan's speed is " + speed);

    }

    public void off() {

        speed = OFF;

        System.out.println("Fan's speed is " + speed);

    }

    public int getSpeed() {

        return speed;

    }

}

 

interface Command {

    public void execute();

    public void undo();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

    public void undo() {

        System.out.println("no command here.");

    }

}

 

class FanHighCommand implements Command {

    Fan fan;

    int preSpeed;

    FanHighCommand(Fan fan) {

        this.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.high();

    }

    public void undo() {

        if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

    }

}

 

class FanOffCommand implements Command {

    Fan fan;

    int preSpeed;

    FanOffCommand(Fan fan) {

        this.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.off();

    }

    public void undo() {

        if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

    public void undo() {

        light.off();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

    public void undo() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

    public void undo() {

        garageDoor.close();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

    public void undo() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

    Command[] offCommands;

    Command noCommand = new noCommand();

    Command lastCommand;

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

        lastCommand = onCommands[slot];

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

        lastCommand = offCommands[slot];

    }

    public void undoButtonDown() {

        lastCommand.undo();

    }

}

 

我们看到FanHighCommandFanOffCommand中有重复的undo,很容易想到,把它们给“抽象工厂”了:

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command onCommand = new LightOnCommand(light);

        Command offCommand = new LightOffCommand(light);

        rc.setControl(0, onCommand, offCommand);

 

        onCommand = new GarageDoorOpenCommand(garageDoor);

        offCommand = new GarageDoorCloseCommand(garageDoor);

        rc.setControl(1, onCommand, offCommand);

 

        rc.onButtonDown(0);

        rc.undoButtonDown();

        rc.offButtonDown(1);

        rc.offButtonDown(0);

        rc.onButtonDown(1);

        rc.undoButtonDown();

 

        Fan fan = new Fan();

        onCommand = new FanHighCommand(fan);

        offCommand = new FanOffCommand(fan);

        rc.setControl(2, onCommand, offCommand);

        rc.onButtonDown(2);

        rc.offButtonDown(2);

        rc.undoButtonDown();

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

class Fan {

    public final int HIGH = 3;

    public final int MEDIUM = 2;

    public final int LOW = 1;

    public final int OFF = 0;

    public int speed = 0;

    public void high() {

        speed = HIGH;

        System.out.println("Fan's speed is " + speed);

    }

    public void low() {

        speed = LOW;

        System.out.println("Fan's speed is " + speed);

    }

    public void medium() {

        speed = MEDIUM;

        System.out.println("Fan's speed is " + speed);

    }

    public void off() {

        speed = OFF;

        System.out.println("Fan's speed is " + speed);

    }

    public int getSpeed() {

        return speed;

    }

}

 

interface Command {

    public void execute();

    public void undo();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

    public void undo() {

        System.out.println("no command here.");

    }

}

 

abstract class FanCommand {

    Fan fan;

    int preSpeed;

    abstract void execute();

    public void undo() {

        if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

    }

}

 

class FanHighCommand extends FanCommand implements Command {

    FanHighCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.high();

    }

}

 

class FanOffCommand extends FanCommand implements Command {

    FanOffCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.off();

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

    public void undo() {

        light.off();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

    public void undo() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

    public void undo() {

        garageDoor.close();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

    public void undo() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

    Command[] offCommands;

    Command noCommand = new noCommand();

    Command lastCommand;

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

        lastCommand = onCommands[slot];

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

        lastCommand = offCommands[slot];

    }

    public void undoButtonDown() {

        lastCommand.undo();

    }

}

 

 

下面我们想让一个按钮实现一串命令:关灯,关电扇,开车库。很显然,用一个新的XXXCommand实现即可。

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        RemoteControl rc = new RemoteControl();

 

        Command onCommand = new LightOnCommand(light);

        Command offCommand = new LightOffCommand(light);

        rc.setControl(0, onCommand, offCommand);

 

        onCommand = new GarageDoorOpenCommand(garageDoor);

        offCommand = new GarageDoorCloseCommand(garageDoor);

        rc.setControl(1, onCommand, offCommand);

 

        rc.onButtonDown(0);

        rc.undoButtonDown();

        rc.offButtonDown(1);

        rc.offButtonDown(0);

        rc.onButtonDown(1);

        rc.undoButtonDown();

 

        Fan fan = new Fan();

        onCommand = new FanHighCommand(fan);

        offCommand = new FanOffCommand(fan);

        rc.setControl(2, onCommand, offCommand);

        rc.onButtonDown(2);

        rc.offButtonDown(2);

        rc.undoButtonDown();

 

        onCommand = new ConsecutiveCommands(light, garageDoor, fan);

        rc.setControl(3, onCommand, null);

        rc.onButtonDown(3);

        rc.undoButtonDown();

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

class Fan {

    public final int HIGH = 3;

    public final int MEDIUM = 2;

    public final int LOW = 1;

    public final int OFF = 0;

    public int speed = 0;

    public void high() {

        speed = HIGH;

        System.out.println("Fan's speed is " + speed);

    }

    public void low() {

        speed = LOW;

        System.out.println("Fan's speed is " + speed);

    }

    public void medium() {

        speed = MEDIUM;

        System.out.println("Fan's speed is " + speed);

    }

    public void off() {

        speed = OFF;

        System.out.println("Fan's speed is " + speed);

    }

    public int getSpeed() {

        return speed;

    }

}

 

interface Command {

    public void execute();

    public void undo();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

    public void undo() {

        System.out.println("no command here.");

    }

}

 

abstract class FanCommand {

    Fan fan;

    int preSpeed;

    abstract void execute();

    public void undo() {

        if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

    }

}

 

class FanHighCommand extends FanCommand implements Command {

    FanHighCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.high();

    }

}

 

class FanOffCommand extends FanCommand implements Command {

    FanOffCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.off();

    }

}

 

class ConsecutiveCommands implements Command {

    Light light;

    Fan fan;

    GarageDoor garageDoor;

    int preSpeed;

    ConsecutiveCommands(Light light, GarageDoor garageDoor, Fan fan) {

        this.light = light;

        this.garageDoor = garageDoor;

        this.fan = fan;

    }

    public void execute() {

        light.off(); //关灯

        preSpeed = fan.getSpeed(); //记录原先的电扇档位

        fan.off(); //关电扇

        garageDoor.open() ; //开车库

    }

    public void undo() {

        light.on();

       

if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

      

 garageDoor.close();

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

    public void undo() {

        light.off();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

    public void undo() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

    public void undo() {

        garageDoor.close();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

    public void undo() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

    Command[] offCommands;

    Command noCommand = new noCommand();

    Command lastCommand;

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

        lastCommand = onCommands[slot];

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

        lastCommand = offCommands[slot];

    }

    public void undoButtonDown() {

        lastCommand.undo();

    }

}

 

 

这里有个问题,就是ConsecutiveCommand给写死了,如果我还需要一个新的连续的命令组合,我就要编写ConsecutiveCommand2ConsecutiveCommand3等等。能不能只写一个,而实现动态配置呢?靠传个参数告诉它要执行哪一串命令可以吗?

package javaapplication30;

 

public class Main {

    public static void main(String[] args) {

        Light light = new Light();

        GarageDoor garageDoor = new GarageDoor();

        Fan fan = new Fan();

        RemoteControl rc = new RemoteControl();

 

        Command fanHighCommand = new FanHighCommand(fan);

        Command fanOffCommand = new FanOffCommand(fan);

        Command garageDoorCloseCommand = new GarageDoorCloseCommand(garageDoor);

        Command garageDoorOpenCommand = new GarageDoorOpenCommand(garageDoor);

        Command lightOffCommand = new LightOffCommand(light);

        Command lightOnCommand = new LightOnCommand(light);

 

        Command[] commands = {lightOffCommand, fanOffCommand, garageDoorOpenCommand};

        Command consecutiveCommands = new ConsecutiveCommands(commands);

       

        rc.setControl(0, fanHighCommand, fanOffCommand);

        rc.setControl(1, garageDoorOpenCommand, garageDoorCloseCommand);

        rc.setControl(2, lightOnCommand, lightOffCommand);       

        rc.setControl(3, consecutiveCommands, null);

       

        for(int i=0;i<=3;i++)

            rc.onButtonDown(i);

    }

}

 

class Light {

    public void on() {

        System.out.println("turn Light on.");

    }

    void off() {

        System.out.println("turn light off");

    }

}

 

class GarageDoor {

    public void open() {

        System.out.println("open GarageDoor");

    }

    public void close() {

        System.out.println("close GarageDoor");

    }

}

 

class Fan {

    public final int HIGH = 3;

    public final int MEDIUM = 2;

    public final int LOW = 1;

    public final int OFF = 0;

    public int speed = 0;

    public void high() {

        speed = HIGH;

        System.out.println("Fan's speed is " + speed);

    }

    public void low() {

        speed = LOW;

        System.out.println("Fan's speed is " + speed);

    }

    public void medium() {

        speed = MEDIUM;

        System.out.println("Fan's speed is " + speed);

    }

    public void off() {

        speed = OFF;

        System.out.println("Fan's speed is " + speed);

    }

    public int getSpeed() {

        return speed;

    }

}

 

interface Command {

    public void execute();

    public void undo();

}

 

class noCommand implements Command {

    public void execute() {

        System.out.println("no command here.");

    }

    public void undo() {

        System.out.println("no command here.");

    }

}

 

abstract class FanCommand {

    Fan fan;

    int preSpeed;

    abstract void execute();

    public void undo() {

        if (preSpeed == fan.HIGH) {

            fan.high();

        }

        else if (preSpeed == fan.MEDIUM) {

            fan.medium();

        }

        else if (preSpeed == fan.LOW) {

            fan.low();

        }

        else if (preSpeed == fan.OFF) {

            fan.off();

        }

    }

}

 

class FanHighCommand extends FanCommand implements Command {

    FanHighCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.high();

    }

}

 

class FanOffCommand extends FanCommand implements Command {

    FanOffCommand(Fan fan) {

        super.fan = fan;

    }

    public void execute() {

        preSpeed = fan.getSpeed();

        fan.off();

    }

}

 

class ConsecutiveCommands implements Command {

    Command[] commands;

    ConsecutiveCommands(Command[] commands) {

        this.commands = commands;

    }

    public void execute() {

        for (int i = 0; i < commands.length; i++) {

            commands[i].execute();

        }

    }

    public void undo() {

        for (int i = 0; i < commands.length; i++) {

            commands[i].undo();

        }

    }

}

 

class LightOnCommand implements Command {

    Light light;

    LightOnCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.on();

    }

    public void undo() {

        light.off();

    }

}

 

class LightOffCommand implements Command {

    Light light;

    LightOffCommand(Light light) {

        this.light = light;

    }

    public void execute() {

        light.off();

    }

    public void undo() {

        light.on();

    }

}

 

class GarageDoorOpenCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorOpenCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.open();

    }

    public void undo() {

        garageDoor.close();

    }

}

 

class GarageDoorCloseCommand implements Command {

    GarageDoor garageDoor;

    GarageDoorCloseCommand(GarageDoor garageDoor) {

        this.garageDoor = garageDoor;

    }

    public void execute() {

        garageDoor.close();

    }

    public void undo() {

        garageDoor.open();

    }

}

 

class RemoteControl {

    Command[] onCommands;

    Command[] offCommands;

    Command noCommand = new noCommand();

    Command lastCommand;

    public RemoteControl() {

        onCommands = new Command[7];

        offCommands = new Command[7];

        for (int i = 0; i < 7; i++) {

            onCommands[i] = noCommand;

            offCommands[i] = noCommand;

        }

    }

    public void setControl(int slot, Command onCommand, Command offCommand) {

        onCommands[slot] = onCommand;

        offCommands[slot] = offCommand;

    }

    public void onButtonDown(int slot) {

        onCommands[slot].execute();

        lastCommand = onCommands[slot];

    }

    public void offButtonDown(int slot) {

        offCommands[slot].execute();

        lastCommand = offCommands[slot];

    }

    public void undoButtonDown() {

        lastCommand.undo();

    }

}

 

 

你可能感兴趣的:(命令模式 Command Pattern)