이전 기사 "한 기사로 PHP의 프로토타입 모드 이해하기"에서 PHP의 프로토타입 모드를 소개했습니다. 이 기사에서는 PHP의 명령 모드를 이해하는 데 도움이 됩니다.
작업 모드 또는 트랜잭션 모드라고도 알려진 명령 모드에서는 많은 교과서에서 레스토랑을 예로 사용합니다. 고객으로서 우리는 주문을 하는 사람이고, 웨이터는 주문을 받는 사람이고, 메뉴는 실제 주문이고, 셰프는 주문을 집행하는 사람입니다.
그럼 이 모델은 무엇을 해결하나요? 메뉴를 수정하고 싶을 때 웨이터에게만 말하면 웨이터가 셰프에게 전달해 줍니다. 즉, 고객과 셰프의 디커플링을 실현한 것입니다. 이는 호출자와 구현자의 분리입니다.
물론 많은 디자인 패턴이 이를 수행할 수 있지만 명령 패턴이 수행할 수 있는 것은 명령 수신자가 여러 명령(웨이터 주문, 음료 가져오기, 요리 제공)을 구현하거나 하나의 명령을 여러 Realizer(핫)에 전달하도록 허용하는 것입니다. 요리 요리사, 차가운 요리 요리사, 메인 요리 요리사). 이것이 바로 명령 패턴이 실제로 작동하는 곳입니다! !
GoF 정의: 요청을 객체로 캡슐화하여 다양한 요청으로 클라이언트를 매개변수화하거나 요청 로그를 기록하고 실행 취소 가능한 Operation
GoF 클래스를 지원합니다. Diagram
코드 구현
class Invoker { public $command; public function __construct($command) { $this->command = $command; } public function exec() { $this->command->execute(); } }
먼저 명령의 수신자 또는 더 적절하게는 명령의 요청자를 정의합니다. 클래스 다이어그램에서 이 단어의 영어 정의는 "신청자"입니다. 즉, 명령을 시작하고 작동합니다.
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 기능이 다시 돌아왔습니다. 추가적으로 팩토리 모드 외에 커맨드 모드를 구현하는 것도 좋은 방법인 것 같습니다. 여기서는 여전히 SMS 및 푸시 인터페이스를 사용하고 있습니다. 더 이상 고민하지 말고 명령 모드를 사용하여 또 다른 인터페이스를 구현해 보겠습니다. 물론 관심 있는 친구는 SMS 철회 기능을 구현할 수 있습니다. 위의 명령 취소가 어떻게 구현되는지 생각해 보세요.
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('这次要搞个大活动,快来注册吧!!');
지침
PHP 비디오 튜토리얼저자: 하드코어 프로젝트 관리자
추천 학습: "
위 내용은 PHP의 명령 패턴에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!