命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
示例—遥控器
新型遥控器具有七个可编程的插槽(每个都可以指定一个不同的家电装置),每个插槽都有对应的开关按钮。这个遥控器还具备一个整体的撤销按钮。这些插槽对应的是多家不同厂商的自动化装置,例如:电灯、风扇、热水器、音响设备和其他类似的可控制装置。需求是能够创建一组控制遥控器的API,让每个插槽都能够控制一个或一组装置。请注意,能够控制目前的装置和任何未来可能出现的装置,这一点是很重要的。
UML图表示
代码演示
命令接口
package Command;
public interface Command {
void execute();
void undo();
}
家用电器基类
package Command;
public class Appliance {
public Appliance(){
}
private String name;
public Appliance(String name){
this.name = name;
}
public void action(String action){
System.out.println((name != null ? name + " " : "") + action);
}
}
风扇
package Command;
public class CeilingFan extends Appliance {
public CeilingFan() {
super();
}
public static final int HIGH = 3;
public static final int MEDIUM = 2;
public static final int LOW = 1;
public static final int OFF = 0;
int speed;
public CeilingFan(String name){
super(name);
speed = OFF;
}
public void high(){
speed = HIGH;
// 设置高转速
action("CeilingFan set high");
}
public void medium(){
speed = MEDIUM;
// 设置中转速
action("CeilingFan set medium");
}
public void low(){
speed = LOW;
// 设置低转速
action("CeilingFan set low");
}
public void off(){
speed = OFF;
// 关闭吊扇
action("CeilingFan is off");
}
public int getSpeed(){
return speed;
}
}
风扇的各种命令子类
package Command;
public class CeilingFanHighCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanHighCommand(CeilingFan ceilingFan){
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.high();
}
@Override
public void undo() {
switch (prevSpeed){
case CeilingFan.HIGH:
ceilingFan.high();
break;
case CeilingFan.MEDIUM:
ceilingFan.medium();
break;
case CeilingFan.LOW:
ceilingFan.low();
break;
case CeilingFan.OFF:
ceilingFan.off();
break;
}
}
}
package Command;
public class CeilingFanLowCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanLowCommand(CeilingFan ceilingFan){
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.low();
}
@Override
public void undo() {
switch (prevSpeed){
case CeilingFan.HIGH:
ceilingFan.high();
break;
case CeilingFan.MEDIUM:
ceilingFan.medium();
break;
case CeilingFan.LOW:
ceilingFan.low();
break;
case CeilingFan.OFF:
ceilingFan.off();
break;
}
}
}
package Command;
public class CeilingFanMediumCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanMediumCommand(CeilingFan ceilingFan){
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.medium();
}
@Override
public void undo() {
switch (prevSpeed){
case CeilingFan.HIGH:
ceilingFan.high();
break;
case CeilingFan.MEDIUM:
ceilingFan.medium();
break;
case CeilingFan.LOW:
ceilingFan.low();
break;
case CeilingFan.OFF:
ceilingFan.off();
break;
}
}
}
package Command;
public class CeilingFanOffCommand implements Command {
CeilingFan ceilingFan;
int prevSpeed;
public CeilingFanOffCommand(CeilingFan ceilingFan){
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
prevSpeed = ceilingFan.getSpeed();
ceilingFan.off();
}
@Override
public void undo() {
switch (prevSpeed){
case CeilingFan.HIGH:
ceilingFan.high();
break;
case CeilingFan.MEDIUM:
ceilingFan.medium();
break;
case CeilingFan.LOW:
ceilingFan.low();
break;
case CeilingFan.OFF:
ceilingFan.off();
break;
}
}
}
车库门
package Command;
public class GarageDoor extends Appliance {
public GarageDoor() {
super();
}
public GarageDoor(String name){
super(name);
}
public void up(){
action("GarageDoor up");
}
public void down(){
action("GarageDoor down");
}
public void stop(){
action("GarageDoor stop");
}
public void lightOn(){
action("GarageDoor's Light is on");
}
public void lightOff(){
action("GarageDoor's Light is off");
}
}
车库门的各种命令子类
package Command;
public class GarageDoorDownCommand implements Command {
GarageDoor garageDoor;
public GarageDoorDownCommand(GarageDoor garageDoor){
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.down();
}
@Override
public void undo() {
garageDoor.up();
}
}
package Command;
public class GarageDoorOpenCommand implements Command {
GarageDoor garageDoor;
public GarageDoorOpenCommand(GarageDoor garageDoor){
this.garageDoor = garageDoor;
}
@Override
public void execute() {
garageDoor.up();
}
@Override
public void undo() {
garageDoor.down();
}
}
电灯
package Command;
public class Light extends Appliance {
public Light() {
super();
}
public Light(String name){
super(name);
}
public void on(){
action("Light is on");
}
public void off(){
action("Light is off");
}
}
电灯的各种命令子类
package Command;
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light){
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
package Command;
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light){
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
音响
package Command;
public class Stereo extends Appliance {
public Stereo() {
super();
}
public Stereo(String name){
super(name);
}
public void on(){
action("Stereo is on");
}
public void off(){
action("Stereo is off");
}
public void setCd() {
action("Stereo set CD");
}
public void setDvd(){
action("Stereo set DVD");
}
public void setRadio(){
action("Stereo set radio");
}
public void setVolume(int volume) {
action("Stereo set volume " + volume);
}
}
音响的各种命令子类
package Command;
public class StereoOffCommand implements Command {
Stereo stereo;
public StereoOffCommand(Stereo stereo){
this.stereo = stereo;
}
@Override
public void execute() {
stereo.off();
}
@Override
public void undo() {
stereo.on();
stereo.setCd();
stereo.setVolume(11);
}
}
package Command;
public class StereoOnWithCDCommand implements Command {
Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo){
this.stereo = stereo;
}
@Override
public void execute() {
stereo.on();
stereo.setCd();
stereo.setVolume(11);
}
@Override
public void undo() {
stereo.off();
}
}
空命令子类
package Command;
public class NoCommand implements Command {
@Override
public void execute() {
// 什么都不做
}
@Override
public void undo() {
// 什么都不做
}
}
批量命令子类(宏命令)
package Command;
public class MacroCommand implements Command {
Command[] commands;
public MacroCommand(Command[] commands){
this.commands = commands;
}
@Override
public void execute() {
for (Command command : commands){
command.execute();
}
}
@Override
public void undo() {
}
}
遥控器
package Command;
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
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;
}
undoCommand = noCommand;
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot){
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPushed(){
undoCommand.undo();
}
@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n---------Remote Control----------\n");
for (int i = 0; i < onCommands.length; i++) {
stringBuffer.append("[slot " + i +"] " + onCommands[i].getClass().getName() +
" " + offCommands[i].getClass().getName() + "\n");
}
return stringBuffer.toString();
}
}
测试代码
package Command;
public class RemoteLoader {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
Light livingRoomLight = new Light("Living Room");
Light kitchenLight = new Light("Kitchen");
GarageDoor garageDoor = new GarageDoor();
Stereo stereo = new Stereo("Living Room");
CeilingFan ceilingFan = new CeilingFan("Living Room");
LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
GarageDoorDownCommand garageDown = new GarageDoorDownCommand(garageDoor);
StereoOnWithCDCommand stereoOnWithCD = new StereoOnWithCDCommand(stereo);
StereoOffCommand stereoOff = new StereoOffCommand(stereo);
CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);
CeilingFanHighCommand ceilingFanHigh = new CeilingFanHighCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan);
remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);
remoteControl.setCommand(1, kitchenLightOn, kitchenLightOff);
remoteControl.setCommand(2, garageOpen, garageDown);
remoteControl.setCommand(3,stereoOnWithCD, stereoOff);
remoteControl.setCommand(4,ceilingFanMedium,ceilingFanOff);
remoteControl.setCommand(5,ceilingFanHigh, ceilingFanOff);
System.out.println(remoteControl);
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.onButtonWasPushed(2);
remoteControl.offButtonWasPushed(2);
remoteControl.onButtonWasPushed(3);
remoteControl.offButtonWasPushed(3);
remoteControl.onButtonWasPushed(4);
remoteControl.offButtonWasPushed(4);
remoteControl.onButtonWasPushed(5);
remoteControl.offButtonWasPushed(5);
System.out.println("~~~~~~~~~~~~~~~~~~~~~测试撤销");
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.undoButtonWasPushed();
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(0);
remoteControl.undoButtonWasPushed();
remoteControl.onButtonWasPushed(4);
remoteControl.offButtonWasPushed(4);
remoteControl.undoButtonWasPushed();
remoteControl.onButtonWasPushed(5);
remoteControl.undoButtonWasPushed();
System.out.println("~~~~~~~~~~~~~~~~~~~~~测试宏命令");
Command[] partyOn = {livingRoomLightOn,kitchenLightOn,garageOpen,stereoOnWithCD,ceilingFanMedium };
Command[] partyOff = {livingRoomLightOff, kitchenLightOff, garageDown, stereoOff, ceilingFanOff};
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
remoteControl.setCommand(6,partyOnMacro, partyOffMacro);
System.out.println(remoteControl);
System.out.println("-----Pushing Macro On--------");
remoteControl.onButtonWasPushed(6);
System.out.println("-----Pushing Macro Of--------");
remoteControl.offButtonWasPushed(6);
}
}
测试结果
---------Remote Control----------
[slot 0] Command.LightOnCommand Command.LightOffCommand
[slot 1] Command.LightOnCommand Command.LightOffCommand
[slot 2] Command.GarageDoorOpenCommand Command.GarageDoorDownCommand
[slot 3] Command.StereoOnWithCDCommand Command.StereoOffCommand
[slot 4] Command.CeilingFanMediumCommand Command.CeilingFanOffCommand
[slot 5] Command.CeilingFanHighCommand Command.CeilingFanOffCommand
[slot 6] Command.NoCommand Command.NoCommand
Living Room Light is on
Living Room Light is off
Kitchen Light is on
Kitchen Light is off
GarageDoor up
GarageDoor down
Living Room Stereo is on
Living Room Stereo set CD
Living Room Stereo set volume 11
Living Room Stereo is off
Living Room CeilingFan set medium
Living Room CeilingFan is off
Living Room CeilingFan set high
Living Room CeilingFan is off
~~~~~~~~~~~~~~~~~~~~~测试撤销
Living Room Light is on
Living Room Light is off
Living Room Light is on
Living Room Light is off
Living Room Light is on
Living Room Light is off
Living Room CeilingFan set medium
Living Room CeilingFan is off
Living Room CeilingFan set medium
Living Room CeilingFan set high
Living Room CeilingFan set medium
~~~~~~~~~~~~~~~~~~~~~测试宏命令
---------Remote Control----------
[slot 0] Command.LightOnCommand Command.LightOffCommand
[slot 1] Command.LightOnCommand Command.LightOffCommand
[slot 2] Command.GarageDoorOpenCommand Command.GarageDoorDownCommand
[slot 3] Command.StereoOnWithCDCommand Command.StereoOffCommand
[slot 4] Command.CeilingFanMediumCommand Command.CeilingFanOffCommand
[slot 5] Command.CeilingFanHighCommand Command.CeilingFanOffCommand
[slot 6] Command.MacroCommand Command.MacroCommand
-----Pushing Macro On--------
Living Room Light is on
Kitchen Light is on
GarageDoor up
Living Room Stereo is on
Living Room Stereo set CD
Living Room Stereo set volume 11
Living Room CeilingFan set medium
-----Pushing Macro Of--------
Living Room Light is off
Kitchen Light is off
GarageDoor down
Living Room Stereo is off
Living Room CeilingFan is off