Menu
Coddy logo textTech

Patron Commande

Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 70 sur 87.

Le Patron Commande est un patron de conception comportemental qui transforme une requête en un objet autonome contenant toutes les informations sur cette requête. Cette transformation vous permet de passer des requêtes comme 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.

Pensez-y comme à un restaurant : au lieu de dire directement au chef quoi cuisiner, vous écrivez votre commande sur un bon. Le serveur (invoker) apporte le bon (command) à la cuisine, où il peut être mis en file d'attente, priorisé ou même annulé. Ce patron de conception découple l'objet qui invoque l'opération de celui qui l'exécute.

Le patron comporte quatre composants clés : une interface Command déclarant la méthode execute, des classes ConcreteCommand qui implémentent des actions spécifiques, un Receiver qui effectue le travail réel, et un Invoker qui déclenche les commandes :

interface Command {
    void execute();
}
class Light {  // Récepteur
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}
class RemoteControl {  // Appelant
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

L'appelant ne sait pas quelle action sera effectuée — il appelle simplement execute() :

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Sortie : La lumière est ALLUMÉE

Le patron de conception Commande (Command Pattern) excelle lorsque vous devez mettre des opérations en file d'attente, implémenter une fonctionnalité d'annulation/rétablissement, ou planifier des tâches 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 d'automatisation de maison intelligente en utilisant le Command Pattern ! Vous allez créer un système où divers appareils domestiques peuvent être contrôlés par des commandes, permettant aux actions d'être mises en file d'attente, exécutées et même stockées pour une utilisation ultérieure — tout comme une télécommande universelle qui n'a pas besoin de savoir comment chaque appareil fonctionne en interne.

Vous organiserez votre code sur quatre fichiers :

  • Command.java : Définissez l'interface Command que toutes les commandes d'appareils implémenteront. Elle doit déclarer une seule méthode execute() qui effectue l'action de la commande.
  • Devices.java : Créez deux classes réceptrices qui représentent les appareils de la maison intelligente :

    Television - possède les méthodes powerOn() qui affiche "TV is now ON", powerOff() qui affiche "TV is now OFF", et setChannel(int channel) qui affiche "TV channel set to " + channel.

    Thermostat - possède les méthodes setTemperature(int temp) qui affiche "Thermostat set to " + temp + " degrees" et turnOff() qui affiche "Thermostat turned OFF".

  • Commands.java : Créez des classes de commandes concrètes qui encapsulent les opérations des appareils :

    TVOnCommand - prend une Television dans son constructeur et appelle powerOn() lors de l'exécution.

    TVOffCommand - prend une Television dans son constructeur et appelle powerOff() lors de l'exécution.

    TVChannelCommand - prend une Television et un int channel dans son constructeur, et appelle setChannel() avec ce canal lors de l'exécution.

    ThermostatSetCommand - prend un Thermostat et un int temperature dans son constructeur, et appelle setTemperature() avec cette valeur lors de l'exécution.

  • Main.java : Créez une classe RemoteControl (l'invocateur) qui possède une méthode setCommand(Command cmd) pour stocker une commande et pressButton() pour exécuter la commande stockée.

    Dans votre méthode principale, vous recevrez deux entrées : un numéro de chaîne de télévision (entier) et une température de thermostat (entier).

    Créez une Television et un Thermostat. Créez une RemoteControl et démontrez le Command Pattern en :

    1. Définissant une TVOnCommand et en appuyant sur le bouton
    2. Définissant une TVChannelCommand avec votre canal d'entrée et en appuyant sur le bouton
    3. Définissant une ThermostatSetCommand avec votre température d'entrée et en appuyant sur le bouton
    4. Définissant une TVOffCommand et en appuyant sur le bouton

Vous recevrez deux entrées dans l'ordre : le canal TV (entier) et la température du thermostat (entier).

Par exemple, avec les entrées 5 et 72, votre sortie serait :

TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFF

Remarquez comment la RemoteControl n'interagit jamais directement avec les appareils — elle ne connaît que l'interface Command. Chaque commande encapsule tout ce qui est nécessaire pour effectuer son action, ce qui facilite l'ajout de nouveaux appareils et de nouvelles commandes sans modifier l'invocateur !

Aide-mémoire

Le Command Pattern (ou patron de commande) est un patron de conception comportemental qui encapsule une requête sous la forme d'un objet, vous permettant ainsi de paramétrer des clients avec différentes requêtes, de mettre en file d'attente ou de journaliser des requêtes, et de prendre en charge des opérations annulables.

Ce patron découple l'objet qui invoque l'opération (invoker) de celui qui l'exécute (receiver).

Composants clés

  • Command : Interface déclarant la méthode execute()
  • ConcreteCommand : Classes implémentant des actions spécifiques
  • Receiver : Objet qui effectue le travail réel
  • Invoker : Objet qui déclenche les commandes

Structure de base

// Interface Command
interface Command {
    void execute();
}

// Receiver
class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// ConcreteCommand
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}

// Invoker
class RemoteControl {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Utilisation

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Résultat : Light is ON

L'appelant (invoker) ne sait pas quelle action sera effectuée — il appelle simplement execute(). Cela rend le système flexible et extensible, idéal pour mettre en file d'attente des opérations, implémenter des fonctionnalités d'annulation/rétablissement (undo/redo) ou planifier des tâches.

Essayez vous-même

import java.util.Scanner;

// TODO: Créer la classe RemoteControl (l'invocateur) avec :
// - la méthode setCommand(Command cmd) pour stocker une commande
// - la méthode pressButton() pour exécuter la commande stockée

class RemoteControl {
    // TODO: Implémenter RemoteControl
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Lire les entrées
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Créer une Television et un Thermostat
        
        // TODO: Créer une RemoteControl
        
        // TODO: Démontrer le Command Pattern :
        // 1. Définir une TVOnCommand et appuyer sur le bouton
        // 2. Définir une TVChannelCommand avec le canal d'entrée et appuyer sur le bouton
        // 3. Définir une ThermostatSetCommand avec la température d'entrée et appuyer sur le bouton
        // 4. Définir une TVOffCommand et appuyer sur le bouton
        
        scanner.close();
    }
}
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