Command模式把发出命令的一方和执行命令的一方分离开来,使得请求的一方不必知道接收的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
它包含下面几个角色:
命令(Command)角色:声明了一个给所有具体命令类的抽象接口。
具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合,实现Execute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。
请求者(Invoker)角色:负责发出命令的一方。
接收者(Receiver)角色:负责具体实施和执行一个请求。
命令模式的一个优点是可以方便的实现undo和redo功能。
下面的例子说明了这点:
先定义Command接口:
abstract class Command
{
public abstract void Execute();
public abstract void UnExecute(); // 支持undo
}
下面定义命令的接收者(Receiver):

Code
// "Receiver"
class Calculator
{
private int curr = 0;
public void Operation(char symbol, int operand)
{
switch(symbol)
{
case '+': curr += operand; break;
case '-': curr -= operand; break;
case '*': curr *= operand; break;
case '/': curr /= operand; break;
}
Console.WriteLine(
"Current value = {0,3} (following {1} {2})",
curr, symbol, operand);
}
}
下面是具体的Command实现,执行接收者的Operation方法:

Code
// "ConcreteCommand"
class CalculatorCommand : Command
{
char symbol;
int operand;
Calculator calculator;
// Constructor
public CalculatorCommand(Calculator calculator,
char symbol, int operand)
{
this.calculator = calculator;
this.symbol = symbol;
this.operand = operand;
}
public override void Execute()
{
calculator.Operation(symbol, operand);
}
public override void UnExecute()
{
calculator.Operation(Undo(symbol), operand);
}
// Private helper function
private char Undo(char symbol)
{
char undo;
switch(symbol)
{
case '+': undo = '-'; break;
case '-': undo = '+'; break;
case '*': undo = '/'; break;
case '/': undo = '*'; break;
default : undo = ' '; break;
}
return undo;
}
} 接下来是Invoker,用它来保存执行过的命令,实现undo和redo功能:

Code
// "Invoker"
class User
{
// Initializers
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();
private int current = 0;
public void Redo(int levels)
{
Console.WriteLine("\n---- Redo {0} levels ", levels);
// Perform redo operations
for (int i = 0; i < levels; i++)
{
if (current < commands.Count - 1)
{
Command command = commands[current++] as Command;
command.Execute();
}
}
}
public void Undo(int levels)
{
Console.WriteLine("\n---- Undo {0} levels ", levels);
// Perform undo operations
for (int i = 0; i < levels; i++)
{
if (current > 0)
{
Command command = commands[--current] as Command;
command.UnExecute();
}
}
}
public void Compute(char symbol, int operand)
{
// Create command operation and execute it
Command command = new CalculatorCommand(
calculator, symbol, operand);
command.Execute();
// Add command to undo list
commands.Add(command);
current++;
}
} 最后是调用的代码:
static void Main()
{
// Create user and let her compute
User user = new User();
user.Compute('+', 100);
user.Compute('-', 50);
user.Compute('*', 10);
user.Compute('/', 2);
// Undo 4 commands
user.Undo(4);
// Redo 3 commands
user.Redo(3);
}