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

C# 設計模式精講:命令模式

     編輯:關於C#

一、命令模式:將請求封裝為對象

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

二、五大角色結構

命令模式類圖

  1. 客戶端:創建具體命令並設定接收者。
  2. 命令角色:抽象介面,聲明 Execute()。
  3. 具體命令:綁定接收者與動作,實現 Execute() 調用接收者操作。
  4. 請求者:持有命令引用,調用 ExecuteCommand() 觸發執行。
  5. 接收者:具體執行請求邏輯的對象。

三、結構型示例


// 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();
    }
}

四、經典類比:玉帝傳旨召悟空

玉帝(客戶端)命太白金星(請求者)傳聖旨(命令)召悟空(接收者)上天。玉帝只管發命令,不管怎麼傳達、何時執行;太白金星負責傳達;悟空自行決定怎麼執行。果不其然,悟空大鬧天宮——命令模式完美體現了請求與執行的分離。

五、關鍵設計決策

命令「輕」與「重」

  • 輕量命令:僅耦合請求者與接收者,轉發調用。
  • 重量命令:封裝所有操作細節,無需接收者。
  • 常見折中:動態決定調用哪個接收者。

Undo/Redo 支持

提供 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);
    }
}

七、適用場景與優缺點

適用場景:

  1. 作為面向對象系統中「回調」的替代方案。
  2. 需在不同時刻指定/排隊/記錄請求;命令對象生命週期獨立於發送者。
  3. 需支持撤銷/恢復操作。
  4. 需將數據更新記入日誌,崩潰後重放恢復。
  5. 需支持事務(封裝一組數據更新命令)。

優點: 新命令易加入、接收者可否決、易設計命令隊列、易實現 Undo/Redo、易記日誌、分離請求與執行、命令類可擴展、支持宏命令(組合模式應用)。

缺點: 可能導致大量具體命令類(幾十至上千),某些系統不切實際。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved