命令模式:就是将将发出请求的对象和执行请求的对象解耦,被解耦的两者之间通过命令对象进行沟通。可以理解为:我们开关灯,不用和灯打交道,我们和开关沟通就可以了,不需要知道具体的实现过程。
不同的对象,对应着不同的命令,所以为了方便扩展,先建立一个接口:
public interface Command {
public void excute();
public void undo();
}
被调用对象:
public class Receiver {
private String description;
public Receiver(String description) {
this.description=description;
}
public String getDescription() {
return description;
}
public void action(){
System.out.println("Receiver 已执行...");
}
public void noAction(){
System.out.println("Receiver 执行已撤销");
}
}
实现command接口
public class MyCommandImpl implements Command{
Receiver receiver;
public MyCommandImpl(Receiver receiver) {
this.receiver=receiver;
}
@Override
public void excute() {
receiver.action();
}
@Override
public void undo() {
receiver.noAction();
}
}
现在需要一个调用者:
public class Invoker {
Command[] commands;//持有多个命令
Command undoCommand; //撤销命令
public Invoker(int size) {
commands=new Command[size];
Command empty=new NoCommand();//空对象,不执行任何动作
for(int i=0;i<size;i++){
commands[i]=empty;
}
undoCommand=empty;
}
public void setCommand(int slot,Command command){
commands[slot]=command;
}
public void invokeCommand(int slot){
commands[slot].excute();
undoCommand=commands[slot];
}
public void undoCommand(){
undoCommand.undo();
}
}
测试:
public class Client {
public static void main(String[] args) {
Invoker invoker=new Invoker(1);//调用者
Receiver receiver=new Receiver("door");
MyCommandImpl commandImpl=new MyCommandImpl(receiver);
invoker.setCommand(0, commandImpl)
invoker.invokeCommand(0);
invoker.undoCommand();
}
}
修改一下,我们可以一次执行一组命令:
public class MacroCommand implements Command {
Command[] commands;
public MacroCommand(Command[] commands) {
this.commands=commands;
}
@Override
public void excute() {
for(int i=0;i<commands.length;i++){
commands[i].excute();
}
}
@Override
public void undo() {
for(int i=commands.length-1;i>=0;i--){
commands[i].undo();
}
}
}
测试:
public class Client {
public static void main(String[] args) {
Invoker invoker=new Invoker(1);//调用者
Receiver receiver=new Receiver("door");
MyCommandImpl commandImpl=new MyCommandImpl(receiver);
Command[] commands={commandImpl,commandImpl,commandImpl,commandImpl,commandImpl};
MacroCommand macroCommand=new MacroCommand(commands);
invoker.setCommand(0, macroCommand);
invoker.invokeCommand(0);
invoker.undoCommand();
}
}