玉帝只發命令,不關心傳遞細節;悟空自行決定如何/何時執行——完美詮釋命令模式解耦本質。
命令類別需儲存:
單層 Undo:儲存最後一個命令。多層 Undo:維護命令歷史清單,逆序執行 UnExecute() 為 Undo,順序執行 Execute() 為 Redo。
// 抽象命令
abstract class Command
{
public abstract void Execute();
public abstract void UnExecute();
}
// 具體命令:計算器操作
class CalculatorCommand : Command
{
private char @operator;
private int operand;
private Calculator calculator;
public CalculatorCommand(Calculator calc, char op, int operand)
{
this.calculator = calc;
this.@operator = op;
this.operand = operand;
}
public override void Execute()
{
calculator.Operation(@operator, operand);
}
public override void UnExecute()
{
calculator.Operation(Undo(@operator), operand);
}
private char Undo(char op)
{
return op switch { '+' => '-', '-' => '+', '*' => '/', '/' => '*', _ => ' ' };
}
}
// 接收者:計算器核心邏輯
class Calculator
{
private int total = 0;
public void Operation(char op, int operand)
{
switch (op)
{
case '+': total += operand; break;
case '-': total -= operand; break;
case '*': total *= operand; break;
case '/': total /= operand; break;
}
Console.WriteLine($"Total = {total} (following {op} {operand})");
}
}
// 發送者:使用者操作歷史管理
class User
{
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();
private int current = 0;
public void Compute(char op, int operand)
{
Command cmd = new CalculatorCommand(calculator, op, operand);
cmd.Execute();
commands.Add(cmd);
current++;
}
public void Undo(int levels)
{
Console.WriteLine($"---- Undo {levels} levels ----");
for (int i = 0; i < levels && current > 0; i++)
((Command)commands[--current]).UnExecute();
}
public void Redo(int levels)
{
Console.WriteLine($"---- Redo {levels} levels ----");
for (int i = 0; i < levels && current < commands.Count - 1; i++)
((Command)commands[current++]).Execute();
}
}
// 客戶端測試
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);
}
}
Total = 100 (following + 100) Total = 50 (following - 50) Total = 500 (following * 10) Total = 250 (following / 2) ---- Undo 4 levels ---- Total = 500 (following * 10) // Undo / Total = 50 (following - 50) // Undo * Total = 100 (following + 100) // Undo - Total = 0 (following + 100) // Undo + ---- Redo 3 levels ---- Total = 100 (following + 100) Total = 50 (following - 50) Total = 500 (following * 10)