Patron Commande
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 56 sur 70.
Le patron Commande est un patron de conception comportemental qui transforme une requête en un objet autonome contenant toutes les informations relatives à celle-ci. Cette transformation vous permet de passer des requêtes comme arguments de méthode, de les mettre en file d'attente, de les journaliser ou de prendre en charge des opérations annulables.
Le patron sépare l'objet qui invoque une opération de l'objet qui sait comment l'exécuter. Il se compose de quatre composants clés : une interface de commande, des commandes concrètes, un récepteur (l'objet qui effectue le travail réel) et un invocateur (l'objet qui déclenche les commandes).
public interface ICommand
{
void Execute();
}
public class Light // Récepteur
{
public void TurnOn() => Console.WriteLine("Light is ON");
public void TurnOff() => Console.WriteLine("Light is OFF");
}
public class TurnOnCommand : ICommand
{
private Light _light;
public TurnOnCommand(Light light) => _light = light;
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private Light _light;
public TurnOffCommand(Light light) => _light = light;
public void Execute() => _light.TurnOff();
}L'invocateur stocke et exécute des commandes sans savoir ce qu'elles font :
public class RemoteControl // Invocateur
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
}
// Utilisation
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton(); // La lumière est ALLUMÉE
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton(); // La lumière est ÉTEINTELe pattern Command est particulièrement puissant pour implémenter la fonctionnalité d'annulation, l'enregistrement de macros ou la mise en file d'attente d'opérations pour une exécution ultérieure. Chaque commande encapsule tout ce qui est nécessaire pour effectuer une action, rendant votre système plus flexible et extensible.
Défi
FacileConstruisons un système de commande pour un éditeur de texte en utilisant le motif de conception Command. Vous allez créer un système où les opérations d'édition telles que l'insertion et la suppression de texte sont encapsulées sous forme d'objets de commande, permettant à l'éditeur de les exécuter via une interface unifiée.
Vous organiserez votre code sur trois fichiers :
Command.cs: Définissez une interfaceICommanddans l'espace de nomsTextEditoravec une seule méthodeExecute(). Créez ensuite deux classes de commande concrètes :InsertCommand- prend unDocumentet une chaînetextdans son constructeur. Lorsqu'elle est exécutée, elle ajoute le texte au document et afficheInserted: {text}DeleteCommand- prend unDocumentet unint countdans son constructeur. Lorsqu'elle est exécutée, elle supprime lescountderniers caractères du document et afficheDeleted: {count} characters
Document.cs: Créez une classeDocumentdans le même espace de noms. C'est votre récepteur (receiver) - l'objet qui effectue réellement les opérations de texte. Il doit comporter :- Un champ de chaîne privé pour stocker le contenu (initialisé à une chaîne vide)
- Une méthode
Append(string text)qui ajoute du texte au contenu - Une méthode
RemoveLast(int count)qui supprime lescountderniers caractères (si count dépasse la longueur du contenu, effacez tout le contenu) - Une méthode
GetContent()qui renvoie le contenu actuel
Program.cs: Créez une classeEditorqui agit comme l'appelant (invoker). Elle doit avoir une méthodeSetCommand(ICommand command)et une méthodeExecuteCommand()qui exécute la commande actuelle. Dans votre code principal, démontrez le motif Command en traitant une série d'opérations d'édition.
Vous recevrez les entrées suivantes :
- Le nombre de commandes à exécuter
- Pour chaque commande : le type de commande (
insertoudelete) suivi soit du texte à insérer, soit du nombre de caractères à supprimer
Après avoir exécuté toutes les commandes, affichez le contenu final du document sur une nouvelle ligne au format Content: {content}.
Par exemple, si les entrées sont :
4
insert
Hello
insert
World
delete
3
insert
!La sortie devrait être :
Inserted: Hello
Inserted: World
Deleted: 3 characters
Inserted: !
Content: Hello Wo!Remarquez comment l'Editor (l'appelant) ne connaît rien à la manipulation de texte - il exécute simplement la commande qui lui est donnée. Les commandes encapsulent à la fois l'action et le récepteur, ce qui facilite l'ajout de nouvelles opérations comme ReplaceCommand sans modifier l'éditeur !
Aide-mémoire
Le pattern Command (ou patron de commande) est un patron de conception comportemental qui encapsule une requête sous la forme d'un objet autonome contenant toutes les informations relatives à cette requête. Cela vous permet de passer des requêtes comme arguments de méthode, de les mettre en file d'attente, de les journaliser ou de prendre en charge des opérations annulables.
Le patron comporte quatre composants clés :
- Interface Command - définit la méthode Execute()
- Commandes concrètes - implémentent l'interface de commande et encapsulent des actions spécifiques
- Récepteur (Receiver) - l'objet qui effectue le travail réel
- Invocateur (Invoker) - l'objet qui déclenche les commandes sans connaître leur implémentation
Interface Command et Commandes concrètes
public interface ICommand
{
void Execute();
}
public class TurnOnCommand : ICommand
{
private Light _light;
public TurnOnCommand(Light light) => _light = light;
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private Light _light;
public TurnOffCommand(Light light) => _light = light;
public void Execute() => _light.TurnOff();
}Récepteur (Receiver)
public class Light
{
public void TurnOn() => Console.WriteLine("Light is ON");
public void TurnOff() => Console.WriteLine("Light is OFF");
}Invocateur (Invoker)
public class RemoteControl
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
}Utilisation
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton(); // Light is ON
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton(); // Light is OFFLe pattern Command est utile pour implémenter des fonctionnalités d'annulation (undo), l'enregistrement de macros ou la mise en file d'attente d'opérations pour une exécution ultérieure. Chaque commande encapsule tout ce qui est nécessaire pour effectuer une action, ce qui rend les systèmes plus flexibles et extensibles.
Essayez vous-même
using System;
using TextEditor;
// TODO: Créer la classe Editor (l'invocateur)
public class Editor
{
// TODO: Ajouter un champ privé pour stocker la commande actuelle
private ICommand _command;
// TODO: Implémenter la méthode SetCommand
public void SetCommand(ICommand command)
{
// TODO: Stocker la commande
}
// TODO: Implémenter la méthode ExecuteCommand
public void ExecuteCommand()
{
// TODO: Exécuter la commande actuelle
}
}
class Program
{
public static void Main(string[] args)
{
// Lire le nombre de commandes
int n = Convert.ToInt32(Console.ReadLine());
// Créer le document (récepteur)
Document document = new Document();
// Créer l'éditeur (invocateur)
Editor editor = new Editor();
// TODO: Traiter chaque commande
for (int i = 0; i < n; i++)
{
string commandType = Console.ReadLine();
// TODO: En fonction de commandType, créer la commande appropriée
// - Si "insert" : lire le texte et créer InsertCommand
// - Si "delete" : lire le nombre et créer DeleteCommand
// Ensuite, définir la commande sur l'éditeur et l'exécuter
}
// TODO: Afficher le contenu final avec le format "Content: {content}"
}
}
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
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et Utilisateur