> 백엔드 개발 > PHP 튜토리얼 > PHP의 명령 패턴에 대한 심층 분석

PHP의 명령 패턴에 대한 심층 분석

青灯夜游
풀어 주다: 2023-04-10 10:36:02
앞으로
2796명이 탐색했습니다.

이전 기사 "한 기사로 PHP의 프로토타입 모드 이해하기"에서 PHP의 프로토타입 모드를 소개했습니다. 이 기사에서는 PHP의 명령 모드를 이해하는 데 도움이 됩니다.

PHP의 명령 패턴에 대한 심층 분석

작업 모드 또는 트랜잭션 모드라고도 알려진 명령 모드에서는 많은 교과서에서 레스토랑을 예로 사용합니다. 고객으로서 우리는 주문을 하는 사람이고, 웨이터는 주문을 받는 사람이고, 메뉴는 실제 주문이고, 셰프는 주문을 집행하는 사람입니다.

그럼 이 모델은 무엇을 해결하나요? 메뉴를 수정하고 싶을 때 웨이터에게만 말하면 웨이터가 셰프에게 전달해 줍니다. 즉, 고객과 셰프의 디커플링을 실현한 것입니다. 이는 호출자와 구현자의 분리입니다.

물론 많은 디자인 패턴이 이를 수행할 수 있지만 명령 패턴이 수행할 수 있는 것은 명령 수신자가 여러 명령(웨이터 주문, 음료 가져오기, 요리 제공)을 구현하거나 하나의 명령을 여러 Realizer(핫)에 전달하도록 허용하는 것입니다. 요리 요리사, 차가운 요리 요리사, 메인 요리 요리사). 이것이 바로 명령 패턴이 실제로 작동하는 곳입니다! !

Gof 클래스 다이어그램 및 설명

GoF 정의: 요청을 객체로 캡슐화하여 다양한 요청으로 클라이언트를 매개변수화하거나 요청 로그를 기록하고 실행 취소 가능한 Operation

GoF 클래스를 지원합니다. Diagram

PHP의 명령 패턴에 대한 심층 분석

코드 구현

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 . &#39;命令正在执行,无法再次执行了!&#39;, PHP_EOL;
        }

    }
    
    public function undo()
    {
        if ($this->state == 1) {
            $this->receiver->undo();
            $this->state = 2;
        } else {
            echo $this->name . &#39;命令未执行,无法撤销了!&#39;, PHP_EOL;
        }
    }
}

class Receiver
{
    public $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function action()
    {
        echo $this->name . &#39;命令执行了!&#39;, PHP_EOL;
    }
    public function undo()
    {
        echo $this->name . &#39;命令撤销了!&#39;, PHP_EOL;
    }
}

// 准备执行者
$receiverA = new Receiver(&#39;A&#39;);
$receiverB = new Receiver(&#39;B&#39;);
$receiverC = new Receiver(&#39;C&#39;);

// 准备命令
$commandOne = new ConcreteCommand($receiverA, &#39;A&#39;);
$commandTwo = new ConcreteCommand($receiverA, &#39;B&#39;);
$commandThree = new ConcreteCommand($receiverA, &#39;C&#39;);

// 请求者
$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();
로그인 후 복사
  • 이번에는 다수의 주문과 다수의 셰프가 한꺼번에 주문하는 문제를 해결했고, 잘못된 주문이 주어졌을 경우 취소되는 문제도 해결했습니다
  • 명령 모드에서 작업 대상을 호출하여 알 수 있음을 알 수 있습니다 구현 방법 작업 개체가 분리됩니다.
  • 이러한 다중 명령 및 다중 실행기 구현은 조합 모드
  • 의 구현과 약간 비슷합니다. 이 경우 새 명령을 추가해도 실행기에 영향을 미치지 않으며 영향을 미치지 않습니다. 고객. 새 클라이언트에 새 명령이 필요한 경우 명령과 요청자만 추가하면 됩니다. 수정이 필요한 경우에도 수정 요청자는 본인에 불과합니다.
  • Laravel 프레임워크의 이벤트 스케줄링 메커니즘에서는 관찰자 모드 외에도 명령 모드의 그림자도 명확하게 볼 수 있습니다.

저희 휴대폰 공장은 실제로 레스토랑이 필요할 때와 다르지 않습니다. 휴대폰을 사용할 때에는 주문이 먼저 이루어지며, 이 주문은 일종의 명령이라고 볼 수 있습니다. 이 순서대로 사용해야 하는 액세서리, CPU 유형, 메모리 유형, 사전 설치된 시스템 등을 지정합니다. 그러면 주조소의 작업자들이 이 순서에 따라 제품을 생산하게 됩니다. 이 과정에서 특정 작업자가 주문을 실행하는지, 작업자 그룹이 실행하는지 걱정할 필요 없이 우리와 인터페이스하는 사람에게 주문을 전달하고 전화가 오기를 기다리기만 하면 됩니다. 수용을 위해 제작되었습니다! !

https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command-up.php

Example

SMS 기능이 다시 돌아왔습니다. 추가적으로 팩토리 모드 외에 커맨드 모드를 구현하는 것도 좋은 방법인 것 같습니다. 여기서는 여전히 SMS 및 푸시 인터페이스를 사용하고 있습니다. 더 이상 고민하지 말고 명령 모드를 사용하여 또 다른 인터페이스를 구현해 보겠습니다. 물론 관심 있는 친구는 SMS 철회 기능을 구현할 수 있습니다. 위의 명령 취소가 어떻게 구현되는지 생각해 보세요.

SMS 전송 클래스 다이어그램

PHP의 명령 패턴에 대한 심층 분석

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 &#39;【阿X云短信】发送:&#39; . $msg, PHP_EOL;
    }
}

class SendAliYunPush
{
    public function action($msg)
    {
        echo &#39;【阿X云推送】发送:&#39; . $msg, PHP_EOL;
    }
}

class SendJiGuangMsg
{
    public function action($msg)
    {
        echo &#39;【极X短信】发送:&#39; . $msg, PHP_EOL;
    }
}

class SendJiGuangPush
{
    public function action($msg)
    {
        echo &#39;【极X推送】发送:&#39; . $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(&#39;这次要搞个大活动,快来注册吧!!&#39;);
로그인 후 복사

지침

  • 이 예제에서는 여전히 다중 명령 및 다중 실행기 모드입니다
  • 이 예제를 추상 팩토리와 비교할 수 있습니다. 동일한 기능이 다른 디자인 패턴을 사용하여 구현되지만 추상 팩토리에는 more 객체를 생성하고 객체를 반환하는 것이며 명령 모드는 동작을 선택하는 것입니다
  • 명령 모드는 명령 대기열을 구성하는 데 매우 적합하다는 것을 알 수 있습니다. 수신자가 요청 거부 여부를 결정할 수 있도록 하며 수신자는 구현자로서 더 많은 발언권을 가집니다
원본 주소: https://juejin.cn/post/6844903950768930823

저자: 하드코어 프로젝트 관리자

추천 학습: "
PHP 비디오 튜토리얼

위 내용은 PHP의 명령 패턴에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿