Menu
Coddy logo textTech

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 ÉTEINTE

Le 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.

challenge icon

Défi

Facile

Construisons 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 interface ICommand dans l'espace de noms TextEditor avec une seule méthode Execute(). Créez ensuite deux classes de commande concrètes :
    • InsertCommand - prend un Document et une chaîne text dans son constructeur. Lorsqu'elle est exécutée, elle ajoute le texte au document et affiche Inserted: {text}
    • DeleteCommand - prend un Document et un int count dans son constructeur. Lorsqu'elle est exécutée, elle supprime les count derniers caractères du document et affiche Deleted: {count} characters
  • Document.cs : Créez une classe Document dans 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 les count derniers 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 classe Editor qui agit comme l'appelant (invoker). Elle doit avoir une méthode SetCommand(ICommand command) et une méthode ExecuteCommand() 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 (insert ou delete) 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 OFF

Le 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}"
    }
}
quiz iconTestez-vous

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