## 定义
    将一个请求封装为一个对象，从而让我们可用不同的请求对客户进行参数化；对请求排队或者记录请求日志，以及支持可撤销的操作。

## 设计的原则和思想
1. 解耦的是行为请求(发起)者和行为实现(执行)者。
2. 不变部分是行为实现者，变化部分是行为请求者。
3. 核心思想是将函数封装成命令对象。


## 一句话概括设计模式
    调用者通过命令类让接受者执行指令。

## 结构中包含的角色
1. Command（抽象命令类）
2. ConcreteCommand（具体命令类）
3. Invoker（调用者,行为请求者,动作的发起者）
4. 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();


## 优点
1. 在不修改代码的情况下创建新的命令。
2. 实现操作的延迟执行。
3. 命令可以相互组合，组合一个复杂命令。
4. 一个命令对象和请求的初始调用者可以有不同的生命期。
5. 可以控制命令的执行流程。异步、延迟、排队执行命令、撤销重做命令、存储命令等。

## 缺点
1. 代码会变得更加复杂。
2. 命令模式是为了松耦合。如果调用者或者具体命令类增多，维护性都会降低。

## 何时使用
1. 需要将请求调用者和请求接收者解耦。
2. 某些请求需要延迟执行。可以将请求写入队列，然后延迟执行队列。  
3. 将特定的方法调用转化为对象。 

## 实际应用场景
1. 操作回滚功能。备忘录模式可能会占用大量内存。命令模式就是反向操作。
2. 实现队列。将命令类序列化放入队列中，然后执行。
3. 电脑开机。开机键就是一个命令。
4. 饭店点菜。每点的一道菜都是一个命令。
