1、 意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排列或记录请求日志,以及支持可撤销的操作。
2、 别名
动作(Action)、事务(Transaction)
3、 适用性
- 抽象出呆执行的动作以参数化某对象。可以用语言中的回调(callback)函数表达这种参数化机制。Command模式是回调机制的一个面向对象的替代品。
- 在不同的时刻指定、排列和执行请求。一个Command对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责请求的命令对象传给另一个不同的进程并在那儿实现该请求。
- 支持取消操作。Command的Excute操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。Command接口必须添加一个Unexecute操作,该操作取消上一次Execute调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并调用Unexecute和Execute来实现重数不限的“取消”和“重做”。
- 支持修改日志。
- 用构建在原来操作上的高层操作构造一个系统。这种结构在支持事务的信息系统中很常见。一个事务封装了对数据的一组变动。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用一种方式调用所有的事务。同时该模式也易于添加新事务以扩展系统。
4、 结构
5、 参与者
Command
——声明执行操作的接口。
ConcreteCommand
——将一个接收者对象绑定于一个动作。
——调用接收者相应的操作,以实现Execute。
Client
——创建一个具体命令对象并设定它的接收者。
Invoker
——要求该命令执行这个请求。
Receiver
——知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
6、 协作
- Client创建一个ConcreteCommand对象并指定它的Receiver对象。
- 某Invoker对象存储该ConcreteCommand对象。
- 该Invoker通过调用Command对象的Execute操作来提交一个请求。如该命令是可撤销的,ConcreteCommand就在执行的Execute操作之前存储当前状态以用于取消该命令。
- ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。
7、 效果
Command模式有以下效果:
1) Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
2) Command是头等的对象。它们可像其他的对象一样呗操纵和扩展。
3) 你可将多个命令装配成一个复和命令。
4) 增加新的Command很容易,因为这无需改变已有的类。
8、 实现
1) 一个命令对象应达到何种智能程度;命令对象的能力可大可小,一个极端是它仅确定一个接收者和执行该请求的动作。另一个极端是它自己实现所有功能,根本不需要额外的接受对象。
2) 支持取消和重做;
3) 避免取消操作过程中的错误积累;
9、 代码示例
Command
- package com.examples.pattern.command;
- /**
- * 命令接口,声明执行的操作
- */
- public interface Command {
- /**
- * 执行命令对应的操作
- */
- public void execute();
- }
- package com.examples.pattern.command;
- /**
- * 具体的命令实现对象
- */
- public class ConcreteCommand implements Command {
- /**
- * 持有相应的接收者对象
- */
- private Receiver receiver = null;
- /**
- * 构造方法,传入相应的接收者对象
- * @param receiver
- */
- public ConcreteCommand(Receiver receiver) {
- this.receiver = receiver;
- }
- @Override
- public void execute() {
- receiver.action();
- }
- }
- package com.examples.pattern.command;
- public class Client {
- public void assemble(){
- //创建接收者
- Receiver receiver = new Receiver();
- //创建命令对象,设定它的接收者
- Command command = new ConcreteCommand(receiver);
- //创建Invoker,把命令对象设置进去
- Invoker invoker = new Invoker();
- invoker.setCommand(command);
- command.execute();
- }
- public static void main(String[] args) {
- Client client = new Client();
- client.assemble();
- }
- }
- package com.examples.pattern.command;
- /**
- * 调用者
- */
- public class Invoker {
- /**
- * 持有命令对象
- */
- private Command command = null;
- /**
- * 设置调用持有者的命令对象
- * @param command
- */
- public void setCommand(Command command) {
- this.command = command;
- }
- public void runCommand(){
- //调用命令对象的执行方法
- command.execute();
- }
- }
- package com.examples.pattern.command;
- /**
- * 接收者对象
- */
- public class Receiver {
- /**
- * 真正执行命令相应的操作
- */
- public void action() {
- System.out.println("this is an anction");
- }
- }
10、相关模式
Composite模式可被用来实现宏命令。
Memento模式可用来保持某个状态,命令用这一状态来取消它的效果。