PHP中的命令模式及其应用方法详解
更新时间:2023-10-17前言
命令模式是一个行为设计模式,它允许您将操作封装为独立的对象,并将请求发送方与接收方分离。此外,它还允许您对请求进行参数化,将方法调用排队或记录请求日志,以及支持可撤销操作。
优点
命令模式的优点包括:
- 降低耦合性。请求方和接收方之间的紧密耦合性被拆分为由单个命令对象表示的更小的、更具体的步骤。
- 可撤销操作。通过将所有命令的状态保存在外部,我们可以还原任何已导致状态更改的操作。这样,您可以在不影响应用程序的情况下,稍后撤消这些操作。
- 很容易添加新命令。要添加新命令,只需创建一个新类,实现相应的逻辑,并确保它知道处理该命令的接收者。
- 支持记录请求日志。由于命令对象完全自足且具有标准化接口,因此我们可以轻松记录事务的日志,以便稍后审计或进行调试。
缺点
命令模式的缺点包括:
- 由于创建了许多小型对象,因此可以使您的代码库和系统变得非常复杂。
- 动态创建命令可能很困难且受限制;对于新方法或命令,必须创建一个新子类。
代码示例
接下来我们将展示一个简单的应用程序,以显示命令模式的用途和优点。在这个示例中,我们将创建一个远程遥控器。
首先,让我们定义一些家电产品和遥控器的接口:
// 电器接口,有打开和关闭方法 interface ElectronicDeviceInterface { public function turnOn(); public function turnOff(); } // 电视机类实现电器接口 class Television implements ElectronicDeviceInterface { public function turnOn() { echo "电视机已打开\r\n"; } public function turnOff() { echo "电视机已关闭\r\n"; } } // 空调类实现电器接口 class AirConditioner implements ElectronicDeviceInterface { public function turnOn() { echo "空调已打开\r\n"; } public function turnOff() { echo "空调已关闭\r\n"; } } // 遥控器接口,有打开、关闭和撤销上一个操作方法 interface RemoteControlInterface { public function turnOn(); public function turnOff(); public function undo(); }
接下来,我们将创建一个遥控器实现遥控器接口,并添加一个执行命令的方法:
class RemoteControl implements RemoteControlInterface { private $electronicDevice; public function __construct(ElectronicDeviceInterface $electronicDevice) { $this->electronicDevice=$electronicDevice; } public function turnOn() { $this->electronicDevice->turnOn(); } public function turnOff() { $this->electronicDevice->turnOff(); } public function undo() { // 撤销操作代码 } }
现在,让我们改进RemoteControl类,以支持记录日志和撤销操作:
class RemoteControl implements RemoteControlInterface { private $electronicDevice; private $history=[]; public function __construct(ElectronicDeviceInterface $electronicDevice) { $this->electronicDevice=$electronicDevice; } public function turnOn() { $this->electronicDevice->turnOn(); $this->history[]='turnOn'; } public function turnOff() { $this->electronicDevice->turnOff(); $this->history[]='turnOff'; } public function undo() { if (!empty($this->history)) { $lastCommand=array_pop($this->history); switch ($lastCommand) { case 'turnOn': $this->electronicDevice->turnOff(); break; case 'turnOff': $this->electronicDevice->turnOn(); break; } } } }
现在,我们已经可以使用遥控器打开或关闭电器对象,并支持撤销上一个操作。同时,我们还可以记录已执行的操作:
// 测试代码 $television=new Television(); $remoteControl=new RemoteControl($television); $remoteControl->turnOn(); // 电视机已打开 $remoteControl->turnOff(); // 电视机已关闭 $remoteControl->undo(); // 操作已撤销 $airConditioner=new AirConditioner(); $remoteControl=new RemoteControl($airConditioner); $remoteControl->turnOn(); // 空调已打开 $remoteControl->turnOff(); // 空调已关闭 $remoteControl->undo(); // 操作已撤销
总结
从以上代码示例可以看出,命令模式允许我们将操作封装为独立的对象,并将请求方与接收方分离。这种分离提供了许多好处,包括更低的耦合度、支持可撤销操作以及更易于扩展和维护。虽然有一些缺点,但这些与新函数或命令的动态创建有关,这并不是命令模式的本质问题。