命令模式(Command pattern),将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
别名
动作(Action),事务(Transcation)。
使用性
1)抽象出待执行的动作以参数化某对象。你可用过程语言中的回调(callback)函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。Command模式是回调机制的一个面向对象的替代品。
2)在不同的时刻指定、排列和执行请求;支持取消操作;支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
3)用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务(transaction)的信息系统中很常见。一个事务封装了对数据的一组变动。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。
结构


参与者
Command
——声明执行操作的接口。
ConcreteCommand
——将一个接收者对象绑定于一个动作。
——调用接收者相应的操作,以实现Execute。
Client
——创建一个具体命令对象并设定它的接收者。
Invoker
——要求该命令执行这个请求。
Receicer
——知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
协作
Client创建一个ConcreteCommand对象并指定它的Receiver对象。某Invoker对象存储该ConcreteCommand对象。
该Invoker通过调用Command对象的Execute操作来提交一个请求。若该命令是可撤消的,ConcreteCommand就在执行Excute操作之前存储当前状态以用于取消该命令。ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。
下图展示了这些对象之间的交互。它说明了Command是如何将调用者和接收者(以及它执行的请求)解耦的。

效果
Command模式有以下效果:
1) Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
2) Command是头等的对象。它们可像其他的对象一样被操纵和扩展。
3) 可将多个命令装配成一个复合命令。一般说来,复合命令是Composite模式的一个实例。
4) 增加新的Command很容易,因为这无需改变已有的类。
实现
1) 一个命令对象应达到何种智能程度;
2) 支持取消(undo)和重做(redo);
3)避免取消操作过程中的错误积累;
4) 使用C++模板。
参考代码
别名
动作(Action),事务(Transcation)。
使用性
1)抽象出待执行的动作以参数化某对象。你可用过程语言中的回调(callback)函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。Command模式是回调机制的一个面向对象的替代品。
2)在不同的时刻指定、排列和执行请求;支持取消操作;支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
3)用构建在原语操作上的高层操作构造一个系统。这样一种结构在支持事务(transaction)的信息系统中很常见。一个事务封装了对数据的一组变动。Command模式提供了对事务进行建模的方法。Command有一个公共的接口,使得你可以用同一种方式调用所有的事务。同时使用该模式也易于添加新事务以扩展系统。
结构
参与者
Command
——声明执行操作的接口。
ConcreteCommand
——将一个接收者对象绑定于一个动作。
——调用接收者相应的操作,以实现Execute。
Client
——创建一个具体命令对象并设定它的接收者。
Invoker
——要求该命令执行这个请求。
Receicer
——知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
协作
Client创建一个ConcreteCommand对象并指定它的Receiver对象。某Invoker对象存储该ConcreteCommand对象。
该Invoker通过调用Command对象的Execute操作来提交一个请求。若该命令是可撤消的,ConcreteCommand就在执行Excute操作之前存储当前状态以用于取消该命令。ConcreteCommand对象对调用它的Receiver的一些操作以执行该请求。
下图展示了这些对象之间的交互。它说明了Command是如何将调用者和接收者(以及它执行的请求)解耦的。
效果
Command模式有以下效果:
1) Command模式将调用操作的对象与知道如何实现该操作的对象解耦。
2) Command是头等的对象。它们可像其他的对象一样被操纵和扩展。
3) 可将多个命令装配成一个复合命令。一般说来,复合命令是Composite模式的一个实例。
4) 增加新的Command很容易,因为这无需改变已有的类。
实现
1) 一个命令对象应达到何种智能程度;
2) 支持取消(undo)和重做(redo);
3)避免取消操作过程中的错误积累;
4) 使用C++模板。
参考代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyCommand
{
abstract class Command
{
protected Receiver reveiver;
public Command(Receiver reveiver)
{
this.reveiver = reveiver;
}
abstract public void Execute();
}
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver)
: base(receiver)
{
}
public override void Execute()
{
reveiver.Action();
}
}
class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExcecuteCommand()
{
command.Execute();
}
}
class Receiver
{
public void Action()
{
Console.WriteLine("Execute request!");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyCommand
{
class Program
{
static void Main(string[] args)
{
Invoker i = new Invoker();
i.SetCommand(new ConcreteCommand(new Receiver()));
i.ExcecuteCommand();
Console.ReadKey();
}
}
}<span style="font-size:18px;">
</span>
总结
敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令
模式,一般就不要捉急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只是在真正需要如
撤销/恢复操作等功能时,把原来定的代码重构为命令模式才有意义。
相关模式
状态模式(state pattern)结构
参考:《设计模式》、《大话设计模式》