定义:将“请求”封装成对象, 以便使用不同的请求、队列、日志来参数化其他对象。 命令模式也支持可撤销的操作。
形象比喻:我有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。”
命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。
在本文中, 我们采用遥控器来阐述命令模式。 我们用遥控器控制家里的电器。命令(如打开电灯, 打开车库门等)对象将动作和接收者(电灯、车库门)包进对象中, 这个对象只暴露一个excute()方法, 当此方法被调用的时候,接收者就会进行这些动作(如电灯打开, 车库门打开)。从外面来看, 其他对象不知道究竟哪个接受者进行了哪个些动作, 只知道如果调用excute()方法, 请求的目的就会达到。
下面是具体程序:
1、命令接收这: 我们这里举例灯、车库门、音箱;
Light.java
public class Light {
private String name;
public Light(String name) {
this.name = name;
}
public void on() {
System.out.println(name + " Light is on");
}
public void off() {
System.out.println(name + " Light is off");
}
}
GarageDoor.java
public class GarageDoor {
private String name;
public GarageDoor(String name) {
this.name = name;
}
public void open() {
System.out.println(name + " Garage Door is open");
}
public void close() {
System.out.println(name + " Garage Door is close");
}
}
Stereo.java
public class Stereo {
private String name;
public Stereo(String name) {
this.name = name;
}
public void on() {
System.out.println(name + " Stereo is on");
}
public void off() {
System.out.println(name + " Stereo is off");
}
public void setCd() {
System.out.println(name + " Stereo set CD");
}
public void setDvd() {
System.out.println(name + " Stereo set DVD");
}
public void setRadio() {
System.out.println(name + " Stereo set Radio");
}
public void setVolume(int i) {
System.out.println(name + " Stereo set Volume : " + i);
}
}
2、命令动作:
我们只给出LightOffCommand、LightOffCommand、StereoOnWithCDCommand、StereoOffCommand的代码; GarageDoorOpenCommand与GarageDoorCloseCommand可以参照下面自行补全;
LightOnCommand.java
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void excute() {
light.on();
}
}
LightOffCommand.java
public class StereoOffCommand implements Command {
Stereo stereo;
public StereoOffCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void excute() {
stereo.off();
}
}
StereoOnWithCDCommand.java
public class StereoOnWithCDCommand implements Command {
Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void excute() {
stereo.on();
stereo.setCd();
stereo.setVolume(11);
}
}
StereoOffCommand.java
public class StereoOffCommand implements Command {
Stereo stereo;
public StereoOffCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void excute() {
stereo.off();
}
}
3、CommandControl, 遥控器控制
Command.java
public interface Command {
public void excute();
}
NoCommand.java 我们将每个按钮指定成NoCommand对象, 以便确保每个按钮都有命令对象。
public class NoCommand implements Command {
@Override
public void excute() {
}
}
RemoteControl.java
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
public RemoteControl() {
onCommands = new Command[7];
offCommands = new Command[7];
Command noCommand = new NoCommand();
for (int i = 0; i < 7; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].excute();
}
public void offButtonWasPushed(int slot) {
offCommands[slot].excute();
}
public String toString() {
StringBuffer stringBuff = new StringBuffer();
stringBuff.append("\n------Remote Control------------\n");
for (int i = 0; i < onCommands.length; i++) {
stringBuff.append("[slot " + i + "]" + onCommands[i].getClass().getName()
+ " " + offCommands[i].getClass().getName() + "\n");
}
return stringBuff.toString();
}
}
4、测试程序
RemoteControlMain.java
public class RemoteControlMain {
static RemoteControl remote = new RemoteControl();
public static void main(String[] args) {
remoteInit();
System.out.println(remote);
remote.onButtonWasPushed(0);
remote.offButtonWasPushed(0);
remote.onButtonWasPushed(1);
remote.onButtonWasPushed(2);
remote.offButtonWasPushed(1);
remote.offButtonWasPushed(2);
remote.onButtonWasPushed(3);
remote.offButtonWasPushed(3);
}
public static void remoteInit() {
Light light1 = new Light("Living Room");
Light light2 = new Light("Kitchen");
GarageDoor door = new GarageDoor("Living Room");
Stereo stereo = new Stereo("Living Room");
//
LightOnCommand lightOn1 = new LightOnCommand(light1);
LightOffCommand lightOff1 = new LightOffCommand(light1);
LightOnCommand lightOn2 = new LightOnCommand(light2);
LightOffCommand lightOff2 = new LightOffCommand(light2);
GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(door);
GarageDoorCloseCommand garageClose = new GarageDoorCloseCommand(door);
StereoOnWithCDCommand stereoOn = new StereoOnWithCDCommand(stereo);
StereoOffCommand stereoOff = new StereoOffCommand(stereo);
remote.setCommand(0, lightOn1, lightOff1);
remote.setCommand(1, lightOn2, lightOff2);
remote.setCommand(2, garageOpen, garageClose);
remote.setCommand(3, stereoOn, stereoOff);
}
}
参考:《Head First模式设计》