命令模式 將一個請求封裝為一個對象,從而可以:
| 角色 | 職責 |
|---|---|
| Command (命令介面) | 聲明執行操作的介面,通常包含 execute() |
| ConcreteCommand (具體命令) | 綁定接收者與動作,實現 execute() 調用接收者方法 |
| Receiver (接收者) | 執行具體業務邏輯 |
| Invoker (請求者/調用者) | 持有命令對象,觸發 execute() |
| Client (客戶端) | 創建具體命令、設置接收者、裝配調用者 |
<?php
// 1. 命令介面
interface Command {
public function execute();
}
// 2. 接收者
class Light {
public function turnOn() { echo "Light is ON
"; }
public function turnOff() { echo "Light is OFF
"; }
}
// 3. 具體命令
class LightOnCommand implements Command {
private $light;
public function __construct(Light $light) { $this->light = $light; }
public function execute() { $this->light->turnOn(); }
}
class LightOffCommand implements Command {
private $light;
public function __construct(Light $light) { $this->light = $light; }
public function execute() { $this->light->turnOff(); }
}
// 4. 調用者
class RemoteControl {
private $command;
public function setCommand(Command $cmd) { $this->command = $cmd; }
public function pressButton() { $this->command->execute(); }
}
// 5. 客戶端
$light = new Light();
$remote = new RemoteControl();
$remote->setCommand(new LightOnCommand($light));
$remote->pressButton(); // Light is ON
$remote->setCommand(new LightOffCommand($light));
$remote->pressButton(); // Light is OFF
?>
為支援 Undo,命令介面可增加 undo() 方法,具體命令記錄執行前狀態。調用者維護命令歷史棧,實現回滾。
interface Command {
public function execute();
public function undo();
}
class DimmerLightOnCommand implements Command {
private $light;
private $prevLevel;
public function __construct(Light $light) { $this->light = $light; }
public function execute() {
$this->prevLevel = $this->light->getLevel();
$this->light->dim(75);
}
public function undo() {
$this->light->dim($this->prevLevel);
}
}
| 優點 | 缺點 |
|---|---|
| 解耦調用者與接收者 | 類數量增加,結構較複雜 |
| 易於新增命令,符合開閉原則 | 過度使用會導致系統過度碎片化 |
| 支援宏命令、隊列、日誌、撤銷 |
命令模式是行為型模式中極具實用價值的一種,善用它能讓系統更靈活、可擴展。