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