Heim  >  Artikel  >  Backend-Entwicklung  >  Eine eingehende Analyse des Befehlsmusters in PHP

Eine eingehende Analyse des Befehlsmusters in PHP

青灯夜游
青灯夜游nach vorne
2021-07-08 18:54:292648Durchsuche

Im vorherigen Artikel „Verstehen Sie den Prototypmodus in PHP in einem Artikel“ haben wir den Prototypmodus in PHP vorgestellt. Dieser Artikel führt Sie zum Verständnis des Befehlsmodus in PHP.

Eine eingehende Analyse des Befehlsmusters in PHP

Befehlsmodus, auch Aktions- oder Transaktionsmodus genannt. In vielen Lehrbüchern werden Restaurants als Beispiel verwendet. Als Kunden sind wir die Besteller, die Kellner sind die Empfänger dieser Bestellung, das Menü ist die eigentliche Bestellung und der Koch ist der Ausführer dieser Bestellung.

Was löst dieses Modell? Wenn Sie das Menü ändern möchten, müssen Sie es nur dem Kellner mitteilen, und er wird es dem Koch mitteilen. Mit anderen Worten: Wir haben die Entkopplung von Kunden und Köchen erreicht. Das ist die Entkopplung von Aufrufern und Implementierern.

Natürlich können viele Entwurfsmuster dies tun, aber das Befehlsmuster kann es einem Befehlsempfänger ermöglichen, mehrere Befehle zu implementieren (Kellner, der Bestellungen aufgibt, Getränke holt, Gerichte serviert) oder einen Befehl an mehrere Realizer weiterzuleiten (heiß Tellerkoch, Kalttellerkoch, Hauptgerichtskoch). Hier kommt das Befehlsmuster wirklich ins Spiel! !

Gof-Klassendiagramm und Erklärung

GoF-Definition: Kapseln Sie eine Anforderung als Objekt, sodass Sie Clients mit unterschiedlichen Anforderungen parametrisieren, Anforderungen in die Warteschlange stellen oder Anforderungsprotokolle aufzeichnen und rückgängig machende Operationen unterstützen können.

GoF-Klasse Diagramm

Eine eingehende Analyse des Befehlsmusters in PHP

Code-Implementierung

class Invoker
{
    public $command;
    
    public function __construct($command)
    {
        $this->command = $command;
    }

    public function exec()
    {
        $this->command->execute();
    }
}

Zuerst definieren wir einen Empfänger eines Befehls, oder besser gesagt, einen Anforderer eines Befehls. Die englische Definition dieses Wortes im Klassendiagramm lautet „supplicant“. Das heißt, es initiiert und führt Befehle aus.

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();
    }
}

Der nächste Schritt ist der Befehl, der unser „Menü“ darstellt. Der Zweck dieses Befehls besteht darin, zu definieren, wer der eigentliche Ausführende ist.

class Receiver
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function action()
    {
        echo $this->name . '命令执行了!', PHP_EOL;
    }
}

Der Taker, also der Executor, ist die Person, die den Auftrag tatsächlich ausführt.

// 准备执行者
$receiverA = new Receiver('A');

// 准备命令
$command = new ConcreteCommand($receiverA);

// 请求者
$invoker = new Invoker($command);
$invoker->exec();

Um den Kunden anzurufen, müssen wir den Testamentsvollstrecker kontaktieren, das heißt, ein Restaurant mit einem guten Koch auswählen (Empfänger), dann die Bestellung vorbereiten, also das Menü (Befehl), und sie schließlich dem Kellner übergeben (Anrufer).

  • Tatsächlich ist das Beispiel dieses Restaurants eine perfekte Analyse des Befehlsmusters
  • Was ist mit dem Versprechen, dass mehrere Bestellungen aufgegeben oder an mehrere Köche gegeben werden können? Keine Sorge, der folgende Code hilft uns, dieses Problem zu lösen

Vollständiger Code: 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();
  • Dieses Mal haben wir das Problem mehrerer Bestellungen und mehrerer Köche gleichzeitig gelöst und auch das Problem gelöst, die falsche Bestellung rückgängig zu machen, wenn sie erteilt wurde.
  • Es ist ersichtlich, dass der Befehlsmodus das Objekt der Operation aufruft und weiß Wie man es implementiert Kunden. Wenn ein neuer Client einen neuen Befehl benötigt, müssen nur der Befehl und der Anforderer hinzugefügt werden. Auch wenn ein Änderungsbedarf besteht, ist dies nur der Änderungsanforderer.
  • Im Ereignisplanungsmechanismus des Laravel-Frameworks ist neben dem Beobachtermodus auch der Schatten des Befehlsmodus deutlich zu erkennen
  • Unsere Mobiltelefonfabrik unterscheidet sich eigentlich nicht von einem Restaurant Gießerei zu produzieren Bei der Nutzung eines Mobiltelefons wird zunächst eine Bestellung aufgegeben, die als Befehl betrachtet werden kann. In dieser Bestellung geben wir an, welches Zubehör verwendet werden muss, welcher CPU-Typ, welcher Speichertyp, welches System vorinstalliert ist usw. Dann werden die Arbeiter in der Gießerei nach dieser Reihenfolge produzieren. Bei diesem Vorgang muss ich mir keine Gedanken darüber machen, ob ein bestimmter Arbeiter oder eine Gruppe von Arbeitern den Auftrag ausführt. Ich muss nur den Auftrag an die Person übergeben, die mit uns interagiert, und dann einfach auf das Telefon warten zur Abnahme produziert! !
https://github.com/zhangyue0503/designpatterns-php/blob/master/09.command/source/command-up.php

Beispiel

Die SMS-Funktion ist zurück, das haben wir gefunden Zusätzlich zum Factory-Modus scheint der Befehlsmodus eine gute Möglichkeit zu sein, dies zu implementieren. Hier verwenden wir immer noch diese SMS- und Push-Schnittstellen. Lassen Sie uns ohne weitere Umschweife eine weitere im Befehlsmodus implementieren. Natürlich können interessierte Freunde dann unsere SMS-Entzugsfunktion implementieren. Überlegen Sie, wie die obige Befehlslöschung implementiert wird.

SMS-Versandklassendiagramm

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;);
Eine eingehende Analyse des Befehlsmusters in PHP

Anleitung

  • In diesem Beispiel handelt es sich immer noch um einen Multi-Befehls- und Multi-Executor-Modus.
  • Sie können dieses Beispiel mit der abstrakten Fabrik vergleichen. Die gleiche Funktion wird mit unterschiedlichen Entwurfsmustern implementiert, es sollte jedoch beachtet werden, dass die abstrakte Fabrik dies hat mehr Es geht darum, Objekte zu erzeugen und Objekte zurückzugeben, und der Befehlsmodus ist eine Verhaltensauswahl
  • Wir können sehen, dass sich der Befehlsmodus sehr gut zum Bilden einer Befehlswarteschlange eignet. Mehrere Befehle ermöglichen die Ausführung von Befehlen nacheinander
  • Es Ermöglicht der empfangenden Partei zu entscheiden, ob sie die Anfrage ablehnt. Der Empfänger hat als Umsetzer mehr Mitspracherecht. Originaladresse: https://juejin.cn/post/6844903950768930823. Autor: Hardcore Project Manager. Lernempfehlung: „
  • PHP-Video-Tutorial

Das obige ist der detaillierte Inhalt vonEine eingehende Analyse des Befehlsmusters in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen