首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 設計模式:命令模式完整指南(三)— 實戰計算機與 Undo/Redo 實作

     編輯:關於C語言

生活範例:玉帝傳旨召孫悟空

  • 玉帝 = 客戶端
  • 太白金星 = 命令發送者
  • 孫悟空 = 接收者
  • 聖旨 = 命令物件

玉帝只發命令,不關心傳遞細節;悟空自行決定如何/何時執行——完美詮釋命令模式解耦本質。

命令模式實作關鍵決策

命令粒度

  • 輕量:僅耦合發送者與接收者
  • 重量:封裝完整業務邏輯
  • 常見:動態決定調用哪個接收者

Undo/Redo 支援

命令類別需儲存:

  1. 接收者物件引用
  2. 操作所需參數
  3. 接收者初始狀態(需接收者提供狀態恢復方法)

單層 Undo:儲存最後一個命令。多層 Undo:維護命令歷史清單,逆序執行 UnExecute() 為 Undo,順序執行 Execute() 為 Redo。

完整計算機範例(支援 Undo/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)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved