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

.NET 設計模式精解(十七):命令模式——將請求封裝為物件,實現調用者與執行者解耦

     編輯:關於.NET

命令模式將「請求」封裝為物件,使不同請求可參數化客戶端,支援排隊、日誌、撤銷/重做操作。核心在於分離「行為請求者」與「行為實現者」,透過抽象命令介面實現鬆耦合。

一、模式意圖與結構

意圖:封裝請求為物件,支援參數化、排隊、日誌、可撤銷操作。(GoF)

結構圖:

命令模式結構圖

二、生活實例:餐廳點單

服務員記錄點單於賬單 (命令物件),廚房依序製作。賬單不依賴菜單內容,可承載不同點單項目:

餐廳點單命令模式示意

三、漸進式實作演示:文件編輯器命令封裝

原始緊耦合設計

public class Document {
    public void Display() => Console.WriteLine("Display");
    public void Undo() => Console.WriteLine("Undo");
    public void Redo() => Console.WriteLine("Redo");
}
// 用戶端直接呼叫 doc.Display(), doc.Undo()...

引入命令模式:抽象命令基類

public abstract class DocumentCommand {
    protected Document _doc;
    public DocumentCommand(Document doc) { _doc = doc; }
    public abstract void Execute();
}
public class DisplayCommand : DocumentCommand {
    public DisplayCommand(Document doc) : base(doc) {}
    public override void Execute() => _doc.Display();
}
public class UndoCommand : DocumentCommand { ... }
public class RedoCommand : DocumentCommand { ... }

Invoker 角色:中介調用者

public class DocumentInvoker {
    private DocumentCommand _displayCmd, _undoCmd, _redoCmd;
    public DocumentInvoker(DocumentCommand d, DocumentCommand u, DocumentCommand r) {
        _displayCmd = d; _undoCmd = u; _redoCmd = r;
    }
    public void Display() => _displayCmd.Execute();
    public void Undo() => _undoCmd.Execute();
    public void Redo() => _redoCmd.Execute();
}

用戶端調用

var doc = new Document();
var invoker = new DocumentInvoker(
    new DisplayCommand(doc), new UndoCommand(doc), new RedoCommand(doc));
invoker.Display(); invoker.Undo(); invoker.Redo();

關鍵點:用戶端不再依賴 Document 具體方法,命令被提升為類別層級,雖違背純粹面向物件原則,但優雅解決請求者/執行者分離問題。

四、ASP.NET MVC Front Controller 中的命令模式應用

前端控制器模式分為 Handler (公共邏輯) 與 Command 樹 (業務命令):

Front Controller Handler 結構

Front Controller Command 結構

核心類別實作

// Handler 接收請求,委派 CommandFactory 選擇命令
public class Handler : IHttpHandler {
    public void ProcessRequest(HttpContext context) {
        Command cmd = CommandFactory.Make(context.Request.Params);
        cmd.Execute(context);
    }
}
// Command 介面
public interface Command { void Execute(HttpContext context); }
// Factory 依參數建立具體命令
public class CommandFactory {
    public static Command Make(NameValueCollection parms) {
        switch (parms["requestParm"]) {
            case "1": return new FirstPortal();
            case "2": return new SecondPortal();
            default: return new FirstPortal();
        }
    }
}
// 抽象重導向命令
public abstract class RedirectCommand : Command {
    protected abstract void OnExecute(HttpContext context);
    public void Execute(HttpContext context) {
        OnExecute(context);
        context.Server.Transfer(...);
    }
}
public class FirstPortal : RedirectCommand {
    protected override void OnExecute(HttpContext context) => context.Items["portalId"] = "1";
}
public class SecondPortal : RedirectCommand {
    protected override void OnExecute(HttpContext context) => context.Items["portalId"] = "2";
}

五、效果、實現要點與適用性

  • 核心目的:分離行為請求者與實現者,「將行為抽象為物件」。
  • 狀態保存:具體命令可保存額外狀態資訊 (支援 Undo/Redo)。
  • 巨集命令:結合 Composite 模式封裝多命令為 MacroCommand。
  • vs 委派:命令模式用「介面-實現」定義行為規範,較嚴格符合抽象原則;委派用函數簽名,較靈活但抽象能力弱。
  • 類別爆炸風險:大量具體命令類可能導致系統不切實際。
  • 適用場景:回調替代、請求排隊/不同時刻執行、Undo/Redo 支援、日誌記錄與崩潰恢復。

六、總結

命令模式簡單而優雅,將請求物件化,實現調用者與執行者解耦,支援豐富的行為擴充場景,是行為型模式中的經典之作。

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