Patron Commande
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 75 sur 91.
Le Patron Commande (Command Pattern) est un patron de conception comportemental qui transforme une requête en un objet autonome contenant toutes les informations relatives à cette requête. Cette transformation vous permet de passer des requêtes en tant qu'arguments de méthode, de retarder ou de mettre en file d'attente l'exécution d'une requête, et de prendre en charge des opérations annulables.
Imaginez un restaurant.
Lorsque vous commandez de la nourriture, le serveur écrit votre commande sur un bon (la commande), l'apporte en cuisine, et le chef l'exécute. Le serveur n'a pas besoin de savoir cuisiner ; il se contente de transmettre la commande.
Cela découple le demandeur de l'exécuteur.
Voici une implémentation de base :
<?php
interface Command {
public function execute(): string;
}class Light {
public function on(): string { return "Light is ON"; }
public function off(): string { return "Light is OFF"; }
}class LightOnCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->on();
}
}class LightOffCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->off();
}
}
L'invocateur déclenche des commandes sans savoir ce qu'elles font :
<?php
class RemoteControl {
public function press(Command $command): string {
return $command->execute();
}
}$light = new Light();
$remote = new RemoteControl();
echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));
Résultat :
Light is ON
Light is OFFLe patron de conception Commande (Command Pattern) excelle lorsque vous devez mettre des opérations en file d'attente, implémenter une fonctionnalité d'annulation ou journaliser des actions. Chaque commande est autonome, ce qui facilite l'ajout de nouvelles commandes sans modifier le code existant.
Défi
FacileConstruisons un système de commande pour éditeur de texte en utilisant le Design Pattern Command. Les éditeurs de texte ont souvent besoin de prendre en charge des opérations telles que l'écriture de texte, la suppression de texte et l'annulation d'actions — chaque opération devient un objet de commande autonome qui peut être exécuté via une interface unifiée.
Vous organiserez votre code sur quatre fichiers :
Command.php— Définissez une interfaceCommandavec une seule méthodeexecute(): string. Cela établit le contrat que toutes les commandes de l'éditeur doivent suivre.TextEditor.php— Créez une classeTextEditorqui représente le récepteur — l'objet qui effectue réellement le travail. Votre éditeur doit :- Stocker le contenu textuel actuel (commencer par une chaîne vide)
- Avoir une méthode
write(string $text): stringqui ajoute du texte au contenu et retourne"Written: [text]" - Avoir une méthode
clear(): stringqui vide le contenu et retourne"Content cleared" - Avoir une méthode
getContent(): stringqui retourne le contenu actuel
Commands.php— Incluez les fichiers Command et TextEditor. Créez deux classes de commande qui implémentent l'interfaceCommand:WriteCommand— Prend unTextEditoret une chaîne de texte dans son constructeur. Sa méthodeexecute()appelle la méthodewrite()de l'éditeur et retourne le résultat.ClearCommand— Prend unTextEditordans son constructeur. Sa méthodeexecute()appelle la méthodeclear()de l'éditeur et retourne le résultat.
main.php— Incluez le fichier Commands. Vous recevrez deux entrées : un type de commande ("write"ou"clear") et une chaîne de texte (utilisée uniquement pour les commandes d'écriture).Créez une instance de
TextEditor. En fonction du type de commande, créez l'objet de commande approprié. Ensuite, créez une fonction d'appelant (invoker) ou un mécanisme simple qui appelleexecute()sur la commande et affiche le résultat.Sur une nouvelle ligne, affichez le contenu actuel de l'éditeur dans ce format :
Content: [content](s'il est vide, affichez simplementContent:sans rien après l'espace).
Ce défi démontre comment le Design Pattern Command encapsule chaque opération sous forme d'objet. L'appelant n'a pas besoin de savoir s'il exécute une commande d'écriture ou d'effacement — il appelle simplement execute() et laisse la commande gérer les détails.
Aide-mémoire
Le Command Pattern (ou patron de conception Commande) est un patron de conception comportemental qui encapsule une requête sous la forme d'un objet autonome contenant toutes les informations relatives à la requête. Cela vous permet de passer des requêtes comme arguments de méthode, de mettre des opérations en file d'attente et de prendre en charge des actions annulables.
Ce patron de conception découple le demandeur (l'appelant ou invoker) de l'exécuteur (le récepteur ou receiver), de la même manière qu'un serveur transmet des commandes à un chef sans avoir besoin de savoir cuisiner.
Structure de base
Définissez une interface Command avec une méthode execute() :
interface Command {
public function execute(): string;
}Créez une classe réceptrice qui effectue le travail réel :
class Light {
public function on(): string { return "Light is ON"; }
public function off(): string { return "Light is OFF"; }
}Implémentez des classes de commandes concrètes qui encapsulent des actions spécifiques :
class LightOnCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->on();
}
}
class LightOffCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->off();
}
}Appelant (Invoker)
L'appelant déclenche les commandes sans connaître les détails de leur implémentation :
class RemoteControl {
public function press(Command $command): string {
return $command->execute();
}
}
$light = new Light();
$remote = new RemoteControl();
echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));Avantages
Le Command Pattern est idéal pour mettre des opérations en file d'attente, implémenter une fonctionnalité d'annulation (undo) ou journaliser des actions. Chaque commande est autonome, ce qui facilite l'ajout de nouvelles commandes sans modifier le code existant.
Essayez vous-même
<?php
require_once 'Commands.php';
// Lire l'entrée
$commandType = trim(fgets(STDIN)); // "write" ou "clear"
$text = trim(fgets(STDIN)); // texte pour la commande write
// TODO: Créer une instance de TextEditor
// TODO: Selon le type de commande, créer l'objet de commande approprié
// - Si "write", créer un WriteCommand avec l'éditeur et le texte
// - Si "clear", créer un ClearCommand avec l'éditeur
// TODO: Créer un mécanisme d'appel (invoker) qui appelle execute() sur la commande
// et affiche le résultat
// TODO: Afficher le contenu actuel de l'éditeur au format : "Content: [content]"
// (si vide, afficher simplement "Content: " sans rien après l'espace)
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie