深入理解Java設計模式之命令模式

一、什麼是命令模式

命令模式是一個高內聚的模式,其定義為:將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數化,對請 求排隊或者記錄請求日志,可以提供命令的撤銷和恢復功能。

在該類圖中,我們看到三個角色:

  • Receiver接受者角色:該角色就是幹活的角色,命令傳遞到這裡是應該被執行的
  • Command命令角色:需要執行的所有命令都在這裡聲明
  • Invoker調用者角色:接收到命令,並執行命令

二、命令模式的使用場景

使用時機:當需要先將一個函數登記上,然後再以後調用此函數時,就需要使用命令模式,其實這就是回調函數。

有時候需要向某些對象發送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是什麼。此時希望用一種松耦合的方式來設計程序,使得請求發送者和請求接收者能夠消除彼此之間的耦合關系

例子:拿訂餐來說,客人需要向廚師發送請求,但是完全不知道這些廚師的名字和聯系方式,也不知道廚師炒菜的方式和步驟。 命令模式把客人訂餐的請求封裝成 command 對象,也就是訂餐中的訂單對象。這個對象可以在程序中被四處傳遞,就像訂單可以從服務員手中傳到廚師的手中。這樣一來,客人不需要知道廚師的名字,從而解開瞭請求調用者和請求接收者之間的耦合關系

三、命令模式的優缺點

優點:

類間解耦:調用者角色與接收者角色之間沒有任何依賴關系,調用者實現功能時隻需調用Command 抽象類的execute方法就可以,不需要瞭解到底是哪個接收者執行。可擴展性:Command的子類可以非常容易地擴展,而調用者Invoker和高層次的模塊Client不產生嚴 重的代碼耦合。命令模式結合其他模式會更優秀:命令模式可以結合責任鏈模式,實現命令族解析任務;結合模板方法模式,則可以減少 Command子類的膨脹問題。

缺點:

命令模式也是有缺點的,請看Command的子類:如果有N個命令,問題就出來 瞭,Command的子類就可不是幾個,而是N個,這個類膨脹得非常大,這個就需要讀者在項 目中慎重考慮使用。

四、命令模式的實現

Receiver類,知道如何實施與執行一個與請求相關的操作,任何類都可能作為一個接受者

class Receiver
{
    public void Action()
    {
        Console.WriteLine("執行請求!");
    }
}

Command類,用來聲明執行操作的接口

abstract class Command
{
    protected Receiver receiver;
    public Command(Receiver receiver)
    {
        this.receiver = receiver;
    }
    abstract public void Execute();
}

ConcreteCommand類,將一個接受者對象綁定於一個動作,調用接受者相應的操作,以實現Execute。

class ConcreteCommand : Command
{
    public ConcreteCommand(Receiver receiver) : base(receiver)
    {
    }
     public override void Execute()
    {
        receiver.Action();
    }
}

Invoker類,要求該命令執行這個請求

class Invoker
{
    private Command command;
    public void SetCommand(Command command)
    {
        this.command = command;
    }
    public void ExecuteCommand()
    {
        command.Execute();
    }
}

客戶端代碼

static void Main(string[] args)
{
    Receiver r = new Receiver();
    Command c = new ConcreteCommand(r);
    Invoker i = new Invoker();
     i.SetCommand(c);
    i.ExecuteCommand();
     Console.Read();
}

五、總結

命令模式的意圖是將一個請求封裝成一個對象,從而使您可以用不同的請求對客戶進行參數化。

命令模式主要解決的問題是在軟件系統中,行為請求者與行為實現者通常是一種緊耦合的關系,但某些場合,比如需要對行為進行記錄、撤銷或重做、事務等處理時,這種無法抵禦變化的緊耦合的設計就不太合適。

在某些場合,比如要對行為進行”記錄、撤銷/重做、事務”等處理,這種無法抵禦變化的緊耦合是不合適的。在這種情況下,如何將”行為請求者”與”行為實現者”解耦?將一組行為抽象為對象,可以實現二者之間的松耦合,這是命令模式的使用場景。

系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作,也可以考慮使用命令模式

命令模式的實現過程通過調用者調用接受者執行命令,順序:調用者→接受者→命令。

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: