命令模式屬行為型模式,又稱行動/交易模式。將請求/操作封裝為對象,實現:請求發送者與接收者解耦、請求參數化、請求排隊/日誌、撤銷/恢復功能。核心在於分離「發出命令」與「執行命令」的責任。

Execute()。Execute() 調用接收者操作。ExecuteCommand() 觸發執行。
// Command pattern -- Structural example
using System;
abstract class Command {
protected Receiver receiver;
public Command(Receiver r) { receiver = r; }
abstract public void Execute();
}
class ConcreteCommand : Command {
public ConcreteCommand(Receiver r) : base(r) {}
public override void Execute() { receiver.Action(); }
}
class Receiver { public void Action() { Console.WriteLine("Called Receiver.Action()"); } }
class Invoker {
private Command command;
public void SetCommand(Command c) { command = c; }
public void ExecuteCommand() { command.Execute(); }
}
public class Client {
public static void Main() {
Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();
i.SetCommand(c); i.ExecuteCommand();
}
}
玉帝(客戶端)命太白金星(請求者)傳聖旨(命令)召悟空(接收者)上天。玉帝只管發命令,不管怎麼傳達、何時執行;太白金星負責傳達;悟空自行決定怎麼執行。果不其然,悟空大鬧天宮——命令模式完美體現了請求與執行的分離。
提供 UnExecute() 需存儲:接收者引用、操作參數、接收者初始狀態。單層 Undo 存最後命令;多層需命令歷史列表,逆序執行 UnExecute() 為 Undo,順序執行 Execute() 為 Redo。
// Command pattern -- Real World example
using System; using System.Collections;
abstract class Command {
abstract public void Execute();
abstract public void UnExecute();
}
class CalculatorCommand : Command {
char @operator; int operand; Calculator calculator;
public CalculatorCommand(Calculator calc, char op, int opd) {
calculator = calc; @operator = op; operand = opd;
}
public char Operator { set { @operator = value; } }
public int Operand { set { operand = value; } }
public override void Execute() { calculator.Operation(@operator, operand); }
public override void UnExecute() { calculator.Operation(Undo(@operator), operand); }
private char Undo(char op) {
switch (op) { case '+': return '-'; case '-': return '+'; case '*': return '/'; case '/': return '*'; default: return ' '; }
}
}
class Calculator {
private int total = 0;
public void Operation(char op, int opd) {
switch (op) { case '+': total += opd; break; case '-': total -= opd; break; case '*': total *= opd; break; case '/': total /= opd; break; }
Console.WriteLine("Total = {0} (following {1} {2})", total, op, opd);
}
}
class User {
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList(); private int current = 0;
public void Redo(int levels) {
Console.WriteLine("---- Redo {0} levels", levels);
for (int i = 0; i < levels; i++) if (current < commands.Count - 1) ((Command)commands[current++]).Execute();
}
public void Undo(int levels) {
Console.WriteLine("---- Undo {0} levels", levels);
for (int i = 0; i < levels; i++) if (current > 0) ((Command)commands[--current]).UnExecute();
}
public void Compute(char op, int opd) {
Command cmd = new CalculatorCommand(calculator, op, opd);
cmd.Execute(); commands.Add(cmd); current++;
}
}
public class Client {
public static void Main() {
User user = new User();
user.Compute('+', 100); user.Compute('-', 50); user.Compute('*', 10); user.Compute('/', 2);
user.Undo(4); user.Redo(3);
}
}
適用場景:
優點: 新命令易加入、接收者可否決、易設計命令隊列、易實現 Undo/Redo、易記日誌、分離請求與執行、命令類可擴展、支持宏命令(組合模式應用)。
缺點: 可能導致大量具體命令類(幾十至上千),某些系統不切實際。