命令模式
命令模式是一种对象行为模式,它将请求封装在对象中,这样它就可作为参数来传递,也可以被存储在历史列表里,或者以其他的方式使用,达到解耦的目的。
定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
使用场景
- 使用命令模式作为”CallBack”在面向对象系统中的替代。”CallBack”讲的便是先将一个函数登记上,然后在以后调用此函数。
- 在不同的时刻指定。排列和执行请求。一个Command对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求的命令对象传送给另外一个不同的进程并在那儿实现该请求。
- 支持取消操作。Command的execute操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command接口必须添加一个unexecute操作,该操作取消上一次execute调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用unexecute和execute来实现重数不限的“取消”和“重做”。
- 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在Command接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘中重新读入记录下来的命令并用execute操作重新执行它们。
- 用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务的信息系统中很常见。一个事务封装了对数据的一组变动。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。
结构
实现
public interface Command {
void execute();
void undo();
}
public class ConcreteCommand implements Command {
private Receiver receiver = null;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
public void execute() {
receiver.action();
}
public void undo() {
receiver.back();
}
}
public class Invoker {
private Command command;
public Invoker(Command cmd){
this.command = cmd;
}
public void action(){
command.execute();
}
public void back(){
command.undo();
}
}
public class Receiver {
public void action(){
System.out.println("执行操作");
}
public void back(){
System.out.println("撤销操作");
}
}
测试
public class Client {
public static void main(String[] args) {
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
//创建请求者,把命令对象设置进去
Invoker invoker = new Invoker(command);
//执行方法
invoker.action();
}
}
运行结果:执行操作
命令模式使得发起命令的对象——客户端,和具体实现命令的对象——接收者对象完全解耦,也就是说发起命令的对象完全不知道具体实现对象是谁,也不知道如何实现。命令模式和组合模式结合使用可以实现宏命令,从而使系统操作更简单,功能更强大。