🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 举个例子 > 想吃大闸蟹, 加工的方式有多种,清蒸、姜葱炒、香辣炒、避风塘炒等,可以任意选择,当然不同的方式价格也有所不同。 > 选择一种加工方式后进行下单,厨师做好了会有专门的服务人员送过来,坐着等就可以了…… > 清蒸, 爆炒, 都是你在给厨师下命令, 虽然你不会做菜, 不知道如何清蒸或者爆炒, 但是照样能吃到美味 > 注意这里有一个很重要的角色就是服务员,她帮你下订单,然后把订单传送给厨师,厨师收到订单后根据订单做餐 ## 代码示例 ```php <?php // 厨师 class Chef { public function steamFood($originalMaterial) { echo $originalMaterial . "清蒸中..." . PHP_EOL; return "清蒸" . $originalMaterial; } public function stirFriedFood($originalMaterial) { echo $originalMaterial . "爆炒中..." . PHP_EOL; return "香辣炒" . $originalMaterial; } } // 订单 abstract class Order { protected $chef; protected $name; protected $originalMaterial; public function __construct($name, $originalMaterial) { $this->chef = new Chef(); $this->name = $name; $this->originalMaterial = $originalMaterial; } public function getDisplayName() { return $this->name . $this->originalMaterial; } public function processingOrder() { } } // 清蒸 class SteamedOrder extends Order { public function __construct($originalMaterial) { parent::__construct("清蒸", $originalMaterial); } public function processingOrder() { if ($this->chef) { return $this->chef->steamFood($this->originalMaterial); } return ""; } } // 香辣炒 class SpicyOrder extends Order { public function __construct($originalMaterial) { parent::__construct("香辣炒", $originalMaterial); } public function processingOrder() { if ($this->chef) { return $this->chef->stirFriedFood($this->originalMaterial); } return ""; } } // 服务员 class Waiter { protected $name; protected $order; public function __construct($name) { $this->name = $name; $this->order = null; } public function receiveOrder($order) { $this->order = $order; echo "服务员" . $this->name . ":您的 " . $order->getDisplayName() . " 订单已经收到,请耐心等待" . PHP_EOL; } public function placeOrder() { $food = $this->order->processingOrder(); echo "服务员" . $this->name . ":您的餐 " . $food . " 已经准备好,请您慢用!" . PHP_EOL; } } // 测试代码 $waiter = new Waiter("Anna"); $steamedOrder = new SteamedOrder("大闸蟹"); echo "客户David:我要一份" . $steamedOrder->getDisplayName(); echo PHP_EOL; $waiter->receiveOrder($steamedOrder); $waiter->placeOrder(); echo PHP_EOL; $spicyOrder = new SpicyOrder("大闸蟹"); echo "客户Tony:我要一份" . $steamedOrder->getDisplayName(); $waiter->receiveOrder($spicyOrder); $waiter->placeOrder(); ``` ``` D:\soft\php72\php.exe D:\project\php_dp\index.php 客户David:我要一份清蒸大闸蟹 服务员Anna:您的 清蒸大闸蟹 订单已经收到,请耐心等待 大闸蟹清蒸中... 服务员Anna:您的餐 清蒸大闸蟹 已经准备好,请您慢用! 客户Tony:我要一份清蒸大闸蟹服务员Anna:您的 香辣炒大闸蟹 订单已经收到,请耐心等待 大闸蟹爆炒中... 服务员Anna:您的餐 香辣炒大闸蟹 已经准备好,请您慢用! Process finished with exit code 0 ``` ## 什么是命令模式? > 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化 1. 命令模式的最大特点是将具体的命令与对应的接收者相关联(捆绑),使得调用方不用关心具体的行动执行者及如何执行 2. 只要发送正确的命令,就能准确无误地完成相应的任务。 3. 就像军队,将军一声令下,士兵就得分秒无差,准确执行。 ![](https://box.kancloud.cn/771ba05886fa8233e7e3ca1b0cf15782_740x337.png) ## 设计要点 **命令模式中主要有四个角色,在设计命令模式时要找到并区分这些角色** 1. **命令(Command)**: 要完成的任务,或要执行的动作,这是命令模式的核心角色。 1. **接收者(Receiver)**: 任务的具体实施方,或行动的真实执行者。 1. **调度者(Invoker)**: 接受任务并发送命令,对接用户的需求并执行内部的命令,负责外部用户与内部命令的交互。 1. **用户(Client)**: 命令的使用者,即真正的用户。 ## 优缺点 **策略模式的优点**: 1. 对命令的发送者与接收者进行解耦,使得调用方不用关系具体的行动执行者及如何执行,只要发送正确的命令即可。 1. 可以很方便地增加新的命令。 **策略模式的缺点**: 1. 在一些系统中可能会有很多的命令,而每一个命令都需要一个具体的类去封装,容易使命令的类急剧膨胀。 ## 应用场景 1. 希望系统发送一个命令(或信号),任务就能得到处理时,如 GUI 中的各种按钮的单击命令;再如自定义一套消息的响应机制。 1. 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互时。 1. 需要请一系列的命令组合成一组操作时,可以使用宏命令的方式。