Maison  >  Article  >  développement back-end  >  Une analyse approfondie du modèle de commande en PHP

Une analyse approfondie du modèle de commande en PHP

青灯夜游
青灯夜游avant
2021-07-08 18:54:292726parcourir

Dans l'article précédent "Comprendre le mode prototype en PHP en un seul article" nous avons présenté le mode prototype en PHP. Cet article vous amènera à comprendre le mode commande en PHP.

Une analyse approfondie du modèle de commande en PHP

Mode commande, également connu sous le nom de mode action ou transaction, de nombreux manuels utiliseront les restaurants comme exemple. En tant que clients, nous sommes les donneurs de commande, les serveurs sont les destinataires de cette commande, le menu est la commande elle-même et le chef est l'exécuteur de cette commande.

Alors, que résout ce modèle ? Lorsque vous souhaitez modifier la carte, il suffit d'en informer le serveur et elle le transmettra au chef. Autrement dit, nous avons réussi le découplage entre clients et chefs. C'est le découplage entre les appelants et les exécutants.

Bien sûr, de nombreux modèles de conception peuvent le faire, mais ce que le modèle de commande peut faire, c'est permettre à un récepteur de commandes d'implémenter plusieurs commandes (serveur passant des commandes, obtenir des boissons, servir des plats) ou relayer une commande à plusieurs Realizer (chaud cuisinier de plat, cuisinier de plat froid, chef de plat principal). C’est là que le modèle de commande entre vraiment en jeu ! !

Diagramme de classe Gof et explication

Définition GoF : encapsulez une requête en tant qu'objet, vous permettant de paramétrer les clients avec différentes requêtes ; diagramme

Implémentation du code

Une analyse approfondie du modèle de commande en PHP

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

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

Nous définissons d'abord un récepteur d'une commande, ou de manière plus appropriée un demandeur d'une commande. La définition anglaise de ce mot dans le diagramme de classes est « suppliant ». Autrement dit, il initie et exécute des commandes.

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();
    }
}
La prochaine étape est la commande, qui est notre "menu". Le but de cette commande est de définir qui est le véritable exécuteur testamentaire.
class Receiver
{
    public $name;

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

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

Le preneur, c'est-à-dire l'exécuteur, est la personne qui exécute réellement l'ordre.

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

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

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

Pour appeler le client, il faut contacter l'exécuteur testamentaire, c'est-à-dire sélectionner un restaurant avec un bon chef (Récepteur), puis préparer la commande, qui est le menu (Commande), et enfin le remettre au serveur (Invocateur).

En fait, l'exemple de ce restaurant est très clair. C'est une analyse parfaite du modèle de commande

Qu'en est-il de la promesse que plusieurs commandes peuvent être passées ou données à plusieurs chefs ? Ne vous inquiétez pas, le code suivant nous aide à résoudre ce problème

  • Code complet : 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();
Cette fois, nous avons résolu le problème de plusieurs commandes et de plusieurs chefs à la fois, et avons également résolu le problème de l'annulation d'une mauvaise commande si elle était donnée.

On peut voir que le mode commande appellera l'objet de l'opération et saura comment l'implémenter. L'objet de l'opération est découplé
    Cette implémentation de plusieurs commandes et plusieurs exécuteurs est un peu comme l'implémentation du
  • mode combinaison
  • Dans ce cas, l'ajout de nouvelles commandes n'affectera pas les exécuteurs, ni l'impact. clients. Lorsqu'un nouveau client nécessite une nouvelle commande, seuls la commande et le demandeur doivent être ajoutés. Même s'il y a un besoin de modification, ce n'est que le demandeur de la modification.
  • Dans le mécanisme de planification d'événements du framework Laravel, en plus du mode observateur, l'ombre du mode commande peut également être clairement visible
  • Notre usine de téléphonie mobile n'est en fait pas différente d'un restaurant Lorsque nous avons besoin d'un. fonderie pour produire Lors de l'utilisation d'un téléphone portable, la commande est passée en premier, et cette commande peut être considérée comme une commande. Dans cet ordre, nous préciserons les accessoires à utiliser, quel type de CPU, quel type de mémoire, quel système est préinstallé, etc. Ensuite, les ouvriers de la fonderie produiront selon cet ordre. Dans ce processus, je n'ai pas à me soucier de savoir si un certain travailleur ou un groupe de travailleurs exécute la commande. Il me suffit de remettre la commande à la personne qui communique avec nous, puis d'attendre que le téléphone soit reçu. produit pour acceptation ! !

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

Exemple

La fonction SMS est de retour, nous avons constaté que De plus, en plus du mode usine, le mode commande semble être un bon moyen de l'implémenter. Ici, nous utilisons toujours ces interfaces SMS et push. Sans plus tarder, implémentons-en une autre en utilisant le mode commande. Bien entendu, les amis intéressés peuvent ensuite mettre en œuvre notre fonction de retrait de SMS. Pensez à la manière dont l'annulation de la commande ci-dessus est mise en œuvre.

Diagramme des classes d'envoi de SMS

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

Une analyse approfondie du modèle de commande en 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;);

Instructions

  • Dans cet exemple, il s'agit toujours d'un mode multi-commandes et multi-exécuteurs
  • Vous pouvez comparer cet exemple avec la fabrique abstraite. La même fonction est implémentée en utilisant différents modèles de conception, mais il convient de noter que la fabrique abstraite a. plus Il s'agit de produire des objets et de renvoyer des objets, et le mode commande est un choix de comportement
  • On voit que le mode commande est très adapté pour former une file d'attente de commandes plusieurs commandes permettent d'exécuter les commandes une par une
  • . Il permet à la partie destinataire de décider de refuser la demande, le destinataire a plus son mot à dire que l'exécutant

Adresse originale : https://juejin.cn/post/6844903950768930823

Auteur : Chef de projet hardcore

Apprentissage recommandé : "Tutoriel vidéo PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer