前回の記事「PHP のプロトタイプ モードを理解する」では PHP のプロトタイプ モードについて紹介しましたが、この記事では PHP のコマンド モードについて説明します。
コマンド モードは、アクション モードまたはトランザクション モードとも呼ばれ、多くの教科書では例としてレストランが使用されます。顧客として、私たちは注文の出し手であり、ウェイターはこの注文の受け取り手であり、メニューは実際の注文であり、シェフはこの注文の実行者です。
それでは、このモデルは何を解決するのでしょうか?メニューを変更したい場合は、ウェイターに伝えるだけで、ウェイターがシェフに伝えてくれるという、お客様とシェフのデカップリングを実現しています。それは、呼び出し側と実装側の分離です。
もちろん、多くのデザイン パターンでこれを行うことができますが、コマンド パターンでできることは、コマンド レシーバーに複数のコマンド (ウェイターが注文を出し、飲み物を受け取り、食べ物を提供する) を実装させたり、コマンドを入力させたりすることです。複数の実装者 (ホット クック、コールド クック、メイン コースのシェフ) に中継されます。ここでコマンド パターンが実際に活躍します。 !
GoF 定義: 顧客に対してさまざまなリクエストを使用できるように、リクエストをオブジェクトとしてカプセル化します。 ; リクエストのキューイングまたはログ記録、および取り消し可能な操作のサポート
GoF クラス図
コード実装
class Invoker { public $command; public function __construct($command) { $this->command = $command; } public function exec() { $this->command->execute(); } }
まず、コマンドの受信者、より適切にはコマンドの要求者を定義します。クラス図におけるこの単語の英語の定義は「supplicant」です。つまり、コマンドを開始して操作します。
abstract class Command { protected $receiver; public function __construct(Receiver $receiver) { $this->receiver = $receiver; } abstract public function execute(); } class ConcreteCommand extends Command { public function execute() { $this->receiver->action(); } }
次のステップはコマンドです。これは「メニュー」です。このコマンドの目的は、実際の実行者が誰であるかを定義することです。
class Receiver { public $name; public function __construct($name) { $this->name = $name; } public function action() { echo $this->name . '命令执行了!', PHP_EOL; } }
テイカー、つまり執行者は、注文を実際に執行する人です。
// 准备执行者 $receiverA = new Receiver('A'); // 准备命令 $command = new ConcreteCommand($receiverA); // 请求者 $invoker = new Invoker($command); $invoker->exec();
クライアントに電話するには、実行者に連絡する必要があります。つまり、優れたシェフがいるレストランを選択し(受信者)、次にメニューである注文を準備し(コマンド)、最後に手渡します。それをウェイター (呼び出し者) に送信します。
完全なコード: https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/ source/command.php
<?php class Invoker { private $command = []; public function setCommand(Command $command) { $this->command[] = $command; } public function exec() { if(count($this->command) > 0){ foreach ($this->command as $command) { $command->execute(); } } } public function undo() { if(count($this->command) > 0){ foreach ($this->command as $command) { $command->undo(); } } } } abstract class Command { protected $receiver; protected $state; protected $name; public function __construct(Receiver $receiver, $name) { $this->receiver = $receiver; $this->name = $name; } abstract public function execute(); } class ConcreteCommand extends Command { public function execute() { if (!$this->state || $this->state == 2) { $this->receiver->action(); $this->state = 1; } else { echo $this->name . '命令正在执行,无法再次执行了!', PHP_EOL; } } public function undo() { if ($this->state == 1) { $this->receiver->undo(); $this->state = 2; } else { echo $this->name . '命令未执行,无法撤销了!', PHP_EOL; } } } class Receiver { public $name; public function __construct($name) { $this->name = $name; } public function action() { echo $this->name . '命令执行了!', PHP_EOL; } public function undo() { echo $this->name . '命令撤销了!', PHP_EOL; } } // 准备执行者 $receiverA = new Receiver('A'); $receiverB = new Receiver('B'); $receiverC = new Receiver('C'); // 准备命令 $commandOne = new ConcreteCommand($receiverA, 'A'); $commandTwo = new ConcreteCommand($receiverA, 'B'); $commandThree = new ConcreteCommand($receiverA, 'C'); // 请求者 $invoker = new Invoker(); $invoker->setCommand($commandOne); $invoker->setCommand($commandTwo); $invoker->setCommand($commandThree); $invoker->exec(); $invoker->undo(); // 新加一个单独的执行者,只执行一个命令 $invokerA = new Invoker(); $invokerA->setCommand($commandOne); $invokerA->exec(); // 命令A已经执行了,再次执行全部的命令执行者,A命令的state判断无法生效 $invoker->exec();
当社の携帯電話工場携帯電話を作るために鋳物工場が必要な場合も、最初に注文を出しますが、この注文は注文とみなしてよいでしょう。この順序で、使用する必要があるアクセサリ、CPU の種類、メモリの種類、プリインストールされているシステムなどを指定します。そして、鋳物工場の労働者はこの注文に従って生産します。このプロセスでは、特定の作業者が注文を実行するのか、それともグループの作業者が実行するのかを気にする必要はなく、インターフェースを担当する人に注文を渡し、あとは携帯電話が届くのを待つだけで済みます。受け入れられるように生産されます! !
https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command-up.php
SMS 送信クラス図
https://github.com/zhangyue0503/designpatterns-php/blob/ master/09.command/source/command-message.php<?php class SendMsg { private $command = []; public function setCommand(Command $command) { $this->command[] = $command; } public function send($msg) { foreach ($this->command as $command) { $command->execute($msg); } } } abstract class Command { protected $receiver = []; public function setReceiver($receiver) { $this->receiver[] = $receiver; } abstract public function execute($msg); } class SendAliYun extends Command { public function execute($msg) { foreach ($this->receiver as $receiver) { $receiver->action($msg); } } } class SendJiGuang extends Command { public function execute($msg) { foreach ($this->receiver as $receiver) { $receiver->action($msg); } } } class SendAliYunMsg { public function action($msg) { echo '【阿X云短信】发送:' . $msg, PHP_EOL; } } class SendAliYunPush { public function action($msg) { echo '【阿X云推送】发送:' . $msg, PHP_EOL; } } class SendJiGuangMsg { public function action($msg) { echo '【极X短信】发送:' . $msg, PHP_EOL; } } class SendJiGuangPush { public function action($msg) { echo '【极X推送】发送:' . $msg, PHP_EOL; } } $aliMsg = new SendAliYunMsg(); $aliPush = new SendAliYunPush(); $jgMsg = new SendJiGuangMsg(); $jgPush = new SendJiGuangPush(); $sendAliYun = new SendAliYun(); $sendAliYun->setReceiver($aliMsg); $sendAliYun->setReceiver($aliPush); $sendJiGuang = new SendJiGuang(); $sendAliYun->setReceiver($jgMsg); $sendAliYun->setReceiver($jgPush); $sendMsg = new SendMsg(); $sendMsg->setCommand($sendAliYun); $sendMsg->setCommand($sendJiGuang); $sendMsg->send('这次要搞个大活动,快来注册吧!!');ログイン後にコピーDescription
#元のアドレス: https://juejin .cn/post/6844903950768930823
- この例では、依然としてマルチコマンドおよびマルチエグゼキュータ モードです。
- この例を抽象ファクトリと比較できます。同じ機能が異なるデザイン パターンを使用して実装されていますが、 note さらに、抽象ファクトリはオブジェクトの生成とオブジェクトの返しに重点を置いているのに対し、コマンド モードは動作の選択です
- コマンド モードはコマンド キューの形成に非常に適していることがわかります。実行を継続します
#これにより、受信側はリクエストを拒否するかどうかを決定でき、受信者は実装者としてより多くの発言権を持ちます PHP ビデオ チュートリアル著者: ハードコア プロジェクト マネージャー
推奨学習: 「以上がPHP のコマンド パターンの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。