1. 模式意图
命令模式又称为动作(Action),事务(Transaction)。
命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
命令模式是对命令的封装;命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接受的一方接到请求,并执行操作。命令模式允许请求的一方和接受的一方独立开来,使得请求的一方不必知道接受请求的一方的接口,更不必知道请求是怎么被接受,以及操作是否被执行,何时执行,以及是怎么被执行的。
命令模式的优点:
- 命令模式使新的命令很容易地被加入到系统里
- 允许接受请求的一方决定是否要否决请求
- 能较容易地设计一个命令队列
- 可以容易地实现对请求的undo和redo
- 在需要的情况下,可以叫容易地将命令计入日志
- 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开
- 可以把命令对象聚合在一起,合成为合成对象;比如宏命令便是合成命令的例子
命令模式的缺点:
- 使用命令模式会导致某些系统有过多的具体命令类
2. 模式定义
Client: 创建了一个具体命令(ConcreteCommand)对象并确定其接受者;
命令(Command): 声明了一个给所有具体命令类的抽象接口;
具体命令(ConcreteCommand): 实现Execute()方法,负责调用接收者的相应操作;
请求者(Invoke): 负责调用命令对象执行请求;
接收者(Receiver): 负责具体实施和执行一个请求,任何一个类都可以成为接收者
如果命令类提供一个方法,如unExecute(),以恢复其操作,那么命令类就可以支持undo和redo;具体命令类需要存储状态信息,包括:
- 接收者对象实际上实施请求所代表的操作
- 对接收者对象所作的操作所需的参数
- 接收者类的最初的状态,接收者必须提供适当的方法,是命令类可以通过调用这个方法,以便接收者恢复原有状态
- 如果只需提供一层undo/redo,那么系统只需要存储最后被执行的那个命令对象,如果需要支持多层undo/redo,那么系统就需要存储被执行的命令的清单
3. 模式实现
3.1 C#实现命令模式
// Command pattern -- Structural example
using System;
// "Command"
abstract class Command
{
// Fields
protected Receiver receiver;
// Constructors
public Command( Receiver receiver )
{
this.receiver = receiver;
}
// Methods
abstract public void Execute();
}
// "ConcreteCommand"
class ConcreteCommand : Command
{
// Constructors
public ConcreteCommand( Receiver receiver ) :
base ( receiver ) {}
// Methods
public override void Execute()
{
receiver.Action();
}
}
// "Receiver"
class Receiver
{
// Methods
public void Action()
{
Console.WriteLine("Called Receiver.Action()");
}
}
// "Invoker"
class Invoker
{
// Fields
private Command command;
// Methods
public void SetCommand( Command command )
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
/// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Create receiver, command, and invoker
Receiver r = new Receiver();
Command c = new ConcreteCommand( r );
Invoker i = new Invoker();
// Set and execute command
i.SetCommand(c);
i.ExecuteCommand();
}
}
4. 模式应用