命令模式:将”请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
一个命令对象通过在特定接受者上绑定一组动作来封装一个请求,要达到这一点,命令对象将动作和接受者包装进对象中。这个对象只暴露一个execute(),当此方法被调用的时候,接受者就会进行这些动作。
[]类图
[]命令模式的实现
命令接口
public interface Command {
void execute();
void undo();
}
命令实现类
public class NoCommand implements Command {
@Override
public void execute() {
}
@Override
public void undo() {
}
}
命令实现类
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
命令实现类
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
命令实现类
public class StereoOnWithCDCommand implements Command {
private Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
stereo.on();
stereo.setCD();
stereo.setVolume();
}
@Override
public void undo() {
stereo.off();
}
}
命令实现类
public class StereoOffWithCDCommand implements Command {
private Stereo stereo;
public StereoOffWithCDCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
stereo.off();
}
@Override
public void undo() {
stereo.on();
stereo.setCD();
stereo.setVolume();
}
}
命令实现类
public class MacroCommand implements Command {
private Command[] commands;
public MacroCommand(Command[] commands) {
this.commands = commands;
}
@Override
public void execute() {
for (int i = 0; i < commands.length; i++) {
commands[i].execute();
}
}
@Override
public void undo() {
}
}
接受者类
public class Light {
public void on() {
System.out.println("light on");
}
public void off() {
System.out.println("light off");
}
}
接受者类
public class Stereo {
public void on() {
System.out.println("stereo on");
}
public void setCD() {
System.out.println("stereo setCD");
}
public void setVolume() {
System.out.println("stereo setVolume");
}
public void off() {
System.out.println("stereo off");
}
}
调用者类
public class RemoteControl {
private Command[] onCommands;
private Command[] offCommands;
private Command undoCommand;
public RemoteControl() {
onCommands = new Command[7];
offCommands = new Command[7];
NoCommand 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 onButtonWasPressed(int slot) {
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButtonWasPressed(int slot) {
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButtonWasPressed() {
undoCommand.undo();
}
}
测试
public static void main(String args[]) {
RemoteControl control = new RemoteControl();
Light light = new Light();
Stereo stereo = new Stereo();
Command lightOnCommand = new LightOnCommand(light);
Command lightOffCommand = new LightOffCommand(light);
Command stereoOnCommand = new StereoOnWithCDCommand(stereo);
Command stereoOffCommand = new StereoOffWithCDCommand(stereo);
control.setCommand(0, lightOnCommand, lightOffCommand);
control.setCommand(1, stereoOnCommand, stereoOffCommand);
control.onButtonWasPressed(0);
System.out.println("****************");
control.offButtonWasPressed(1);
System.out.println("****************");
control.undoButtonWasPressed();
System.out.println("****************");
Command[] partyOn = {lightOnCommand, stereoOnCommand};
Command[] partyOff = {lightOffCommand, stereoOffCommand};
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
control.setCommand(2, partyOnMacro, partyOffMacro);
control.onButtonWasPressed(2);
System.out.println("****************");
control.offButtonWasPressed(2);
}
[]
()命令模式的用途:队列请求,日程安排,线程池,工作队列等。
()命令模式将发送请求的对象和执行请求的对象解耦。
()在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接收者和一个或者一组动作。
()调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用。
()命令可以支持撤销,做法是实现一个undo()来回到execute()被执行前的状态。
()宏命令是命令的一种简单延伸,允许调用多个命令,宏方法也可以支持撤销。