設計模式-15命令模式(Command Pattern)

  • 2020 年 3 月 13 日
  • 筆記

1.模式動機

在軟件設計中,我們經常需要向某些對象發送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是哪個,我們只需在程序運行時指定具體的請求接收者即可,此時,可以使用命令模式來進行設計,使得請求發送者與請求接收者消除彼此之間的耦合,讓對象之間的調用關係更加靈活。

命令模式可以對發送者和接收者完全解耦,發送者與接收者之間沒有直接引用關係,發送請求的對象只需要知道如何發送請求,而不必知道如何完成請求。這就是命令模式的模式動機。

2.模式定義

命令模式(Command Pattern):將一個請求封裝為一個對象,從而使我們可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日誌,以及支持可撤銷的操作。

命令模式是一種對象行為型模式,其別名為動作(Action)模式或事務(Transaction)模式。

3.模式結構

  • 抽象命令類(Command):聲明執行命令的接口,擁有執行命令的抽象方法 execute()。
  • 具體命令角色(Concrete Command):是抽象命令類的具體實現類,它擁有接收者對象,並通過調用接收者的功能來完成命令要執行的操作。
  • 實現者/接收者(Receiver):執行命令功能的相關操作,是具體命令對象業務的真正實現者。
  • 調用者/請求者(Invoker):是請求的發送者,它通常擁有很多的命令對象,並通過訪問命令對象來執行相關請求,它不直接訪問接收者。

具體調用順序為 Client => Invoker => Concreate Command => Receiver。
Invoker 並不直接調用 Receiver,而是通過具體命令對象來調用實現者。

4.模式代碼

# 實現者/接受者  public class Receiver {      public void action() {          System.out.println("接受者的 Action 方法");      }  }    # 抽象命令類  public abstract class Command {      public abstract void execute();  }    # 具體命令類,內部 new 了一個實現者的對象  public class ConcreteCommand extends Command {      private Receiver receiver;        public ConcreteCommand() {          this.receiver = new Receiver();      }        @Override      public void execute() {          receiver.action();      }  }    # 調用者/請求者,通過賦予不同的 command 值來調用不同的的 command  public class Invoker {      private Command command;        public Invoker(Command command) {          this.command = command;      }        public void setCommand(Command command) {          this.command = command;      }        public void call() {          System.out.println("call 執行命令 Command");          command.execute();      }  }    # Client  public class Client {      public static void main(String[] args) {          Command cmd = new ConcreteCommand();          Invoker invoker = new Invoker(cmd);          invoker.call();      }  }

首先把它們的調用關係理清楚了就明白這個模式了。

5.總結

分析
命令模式的本質是對命令進行封裝,將發出命令的責任和執行命令的責任分割開。

  • 每一個命令都是一個操作:請求的一方發出請求,要求執行一個操作;接收的一方收到請求,並執行操作。
  • 命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求是怎麼被接收,以及操作是否被執行、何時被執行,以及是怎麼被執行的。
  • 命令模式使請求本身成為一個對象,這個對象和其他對象一樣可以被存儲和傳遞。
  • 命令模式的關鍵在於引入了抽象命令接口,且發送者針對抽象命令接口編程,只有實現了抽象命令接口的具體命令才能與接收者相關聯。

優點

  • 降低系統的耦合度。
  • 新的命令可以很容易地加入到系統中。
  • 可以比較容易地設計一個命令隊列和宏命令(組合命令)。
  • 可以方便地實現對請求的Undo和Redo。

缺點

  • 使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。