一、意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。
二、适用性
当有以下需求时,可使用Command模式:
- 当需要抽象出待执行的动作作为参数化对象时。你可用过程语言中的回调(callback)函数来表示这种参数化机制。Command模式是回调机制的一个面向对象那个的替代品。
- 在不同的时刻指定、排列和执行请求。一个Command对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就将负责该请求的命令对象传送给另一个不同的进程并在那儿实现该请求。
- 支持取消操作。Command的Excute操作可在实施操作前将状态存储起来,在取消操作时,这个状态用来消除该操作的影响。Command接口必须添加一个Unexecute操作,该操作取消上一次Execute调用效果,执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并调用Unexecute和Execute来实现重数不限的“取消”和重做“。
- 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。在Command接口中添加装载操作和存储操作,可以用来保持变动的一个一致的修改日志。从崩溃中恢复的过程包括从磁盘总重新读入记录下来的命令并用Execute操作重新执行他们。
- 用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事物(transaction)的信息系统中很常见。一个事物封装了对数据的一组变动。Command模式提供了对事物进行建模的方法。Command有一个公共接口,使得你可以用同一种方式调用所有的事物。同时使用该模式也易于添加新事物以扩展系统。
三、结构
四、代码
public class Receiver {
public void action(){
System.out.println("执行具体的操作");
}
}
public interface Command {
/**
* 执行具体操作的命令
*/
void execute();
}
public class ConcreteCommand implements Command {
private Receiver receiver ;
public ConcreteCommand(Receiver receiver){
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}
public class Invoker {
private Command command;
public Invoker(Command command){
this.command = command;
}
public void action(){
command.execute();
}
}
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();
}
}
输出结果
执行具体的操作