定義
將一個請求封裝為一個物件,從而讓我們可用不同的請求對客戶進行引數化;對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。
設計的原則和思想
- 解耦的是行為請求(發起)者和行為實現(執行)者。
- 不變部分是行為實現者,變化部分是行為請求者。
- 核心思想是將函式封裝成命令物件。
一句話概括設計模式
呼叫者透過命令類讓接受者執行指令。
結構中包含的角色
- Command(抽象命令類)
- ConcreteCommand(具體命令類)
- Invoker(呼叫者,行為請求者,動作的發起者)
- Receiver(接收者,行為實現者,動作的承受者)
最小可表達程式碼
class Receiver
{
public function action()
{
echo '執行命令的具體邏輯';
}
}
interface Command
{
public function execute();
}
class ConcreteCommand implements Command
{
private $receiver;
public function __construct()
{
$this->receiver = new Receiver();
}
public function execute()
{
$this->receiver->action();
}
}
class Invoker
{
private $command;
public function __construct(Command $command)
{
$this->command = $command;
}
public function call()
{
$this->command->execute();
}
}
$invoker = new Invoker(new ConcreteCommand());
$invoker->call();
優點
- 在不修改程式碼的情況下建立新的命令。
- 實現操作的延遲執行。
- 命令可以相互組合,組合一個複雜命令。
- 一個命令物件和請求的初始呼叫者可以有不同的生命期。
- 可以控制命令的執行流程。非同步、延遲、排隊執行命令、撤銷重做命令、儲存命令等。
缺點
- 程式碼會變得更加複雜。
- 命令模式是為了松耦合。如果呼叫者或者具體命令類增多,維護性都會降低。
何時使用
- 需要將請求呼叫者和請求接收者解耦。
- 某些請求需要延遲執行。可以將請求寫入佇列,然後延遲執行佇列。
- 將特定的方法呼叫轉化為物件。
實際應用場景
- 操作回滾功能。備忘錄模式可能會佔用大量記憶體。命令模式就是反向操作。
- 實現佇列。將命令類序列化放入佇列中,然後執行。
- 電腦開機。開機鍵就是一個命令。
- 飯店點菜。每點的一道菜都是一個命令。
本作品採用《CC 協議》,轉載必須註明作者和本文連結