Command Pattern的目的在于分离命令的发出者和命令的执行者。就好比在饭店吃饭,作为客户(命令的发出者),你无需直接跟厨师说明要点什么菜,只要把菜单给服务员就行了,而服务员并不负责烧菜,只要把菜单交给厨师(执行者)即可,厨师会根据菜单做菜了。这两者被分离了。
下面来实现这个点菜的过程:我们要点两个菜,burger和malt。最简单的实现如下:
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();
}
}
这里我们发现Manu1和Manu2两个类形式几乎相通,只是orderup()函数内执行的东西不一样。在主函数中,要执行第二个菜单还得重新生成一个对象,Manu2 manu2=new Manu2(cook); 而不能直接切换,manu1=new Manu2(cook); 这很不爽,由此很容易想到用一个父类,让Manu1,Manu2继承之,如下:
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这个对象来装载各种菜单,并对厨师发出点菜的命令(通过调用Manu的orderup方法)。如下:
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();
}
}
在这个程序里,我们发现其实Waitress在主程序中只知道要callCook()
waitress.callCook();
而她并不知道callCook()在具体执行什么,因为Waitress类中的manu是一个抽象类的对象,而callCook()方法中的manu.orderup() 是抽象方法,鬼知道它的具体实现是什么。
这就是Command Pattern的目的:把命令封装成对象(Manu1,Manu2),让调用命令的人(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,对应一个按钮。现在如果要实现7个slot,每个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参数。
如果想要有7个slot,每个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();
}
}
电器的功能可能不止“开”和“关”,比如电风扇,有换挡功能。对于电风扇的High,Medium,Low三个档位,每个要写一个单独的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();
}
}
我们看到FanHighCommand和FanOffCommand中有重复的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给写死了,如果我还需要一个新的连续的命令组合,我就要编写ConsecutiveCommand2,ConsecutiveCommand3等等。能不能只写一个,而实现动态配置呢?靠传个参数告诉它要执行哪一串命令可以吗?
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();
}
}