定义:
命令模式(Command):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
结构:
- Command:命令抽象类,用来声明执行操作的接口。
- ConcreteCommand:具体命令类,将一个接收者对象绑定于一个动作,调用接收者相应的操作。
- Invoker:命令发送者,要求该命令执行这个请求。
- Receiver:命令接收者,知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。
- Client:客户端代码,创建一个具体命令对象并设定它的接收者。
代码实例:
/**
* 命令抽象类
* Interface Command
*/
interface Command
{
/**
* @return mixed
*/
public function execute();
}
/**
* 具体命令类
* Class ConcreteCommand
*/
class ConcreteCommand implements Command
{
/**
* @var Receiver
*/
protected $receiver;
/**
* ConcreteCommand constructor.
* @param Receiver $receiver
*/
public function __construct(Receiver $receiver)
{
$this->receiver = $receiver;
}
/**
* @return mixed|void
*/
public function execute()
{
// TODO: Implement execute() method.
$this->receiver->action();
}
}
/**
* 命令发送者
* Class Invoker
*/
class Invoker
{
/**
* @var
*/
protected $command;
/**
* @param Command $command
*/
public function setCommand(Command $command)
{
$this->command = $command;
}
/**
* 执行
*/
public function run()
{
$this->command->execute();
}
}
/**
* 命令接收者
* Class Receiver
*/
class Receiver
{
/**
* 执行请求
*/
public function action()
{
echo "执行请求";
}
}
# 客户端代码
// 设定接收者
$receiver = new Receiver();
$command = new ConcreteCommand($receiver);
// 发送命令
$invoker = new Invoker();
$invoker->setCommand($command);
$invoker->run();
总结:
- 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开;能较容易地设计一个命令队列;在需要的情况下,可以较容易地将命令记录日志;允许接收请求的一方决定是否要否决请求;可以容易地实现对请求地撤销和重做;由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
- 命令模式的缺点是可能会导致有过多的具体命令类。
- 命令模式适用于希望将行为请求者和行为实现者解耦,不直接打交道;希望分离掉行为请求者一部分的责任,行为请求者只需要将命令发给调用者,不再主动的去让行为实现者产生行为,符合单一职责原则;希望可以控制执行的命令列表,方便记录,撤销/重做以及事务等功能;期待可以将请求排队,有序执行。