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 Command 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 transmettre 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 les opérations pouvant être annulées.

Imaginez cela comme un restaurant : au lieu de dire directement au chef quoi cuisiner, vous écrivez votre commande sur un bon. Le serveur (invocateur) apporte le bon (commande) en cuisine, où elle peut être mise en file d’attente, priorisée ou même annulée. Ce modèle découple l’objet qui invoque l’opération de celui qui l’exécute.

Le modèle 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 {  // Invocateur
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

L’invocateur 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 : Light is ON

Le modèle Command se révèle particulièrement utile 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, ce qui rend votre système plus flexible et extensible.

challenge icon

Défi

Facile

Construisons un système domotique intelligent à l’aide du modèle Command ! Vous allez créer un système dans lequel différents appareils domestiques peuvent être contrôlés via des commandes, ce qui permet de mettre des actions en file d’attente, de les exécuter et même de les stocker pour une utilisation ultérieure, comme une télécommande universelle qui n’a pas besoin de savoir comment fonctionne chaque appareil 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 représentant des appareils domestiques intelligents :

    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 - reçoit un Television dans son constructeur et appelle powerOn() lors de son exécution.

    TVOffCommand - reçoit un Television dans son constructeur et appelle powerOff() lors de son exécution.

    TVChannelCommand - reçoit un Television et un int channel dans son constructeur, puis appelle setChannel() avec ce canal lors de son exécution.

    ThermostatSetCommand - reçoit un Thermostat et un int temperature dans son constructeur, puis appelle setTemperature() avec cette valeur lors de son 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 une méthode pressButton() pour exécuter la commande stockée.

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

    Créez un Television et un Thermostat. Créez un RemoteControl et illustrez le modèle Command en :

    1. définissant un TVOnCommand et en appuyant sur le bouton
    2. définissant un TVChannelCommand avec votre chaîne saisie et en appuyant sur le bouton
    3. définissant un ThermostatSetCommand avec votre température saisie et en appuyant sur le bouton
    4. définissant un TVOffCommand et en appuyant sur le bouton

Vous recevrez deux entrées dans l’ordre : la chaîne TV (entier), puis 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 que le RemoteControl n’interagit jamais directement avec les appareils. Il 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 !

Essayez vous-même

import java.util.Scanner;

// TODO: Créer la classe RemoteControl (l'invocateur) avec :
// - méthode setCommand(Command cmd) pour stocker une commande
// - 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 un Television et un Thermostat
        
        // TODO: Créer un RemoteControl
        
        // TODO: Démontrer le pattern Command :
        // 1. Définir un TVOnCommand et appuyer sur le bouton
        // 2. Définir un TVChannelCommand avec le canal d'entrée et appuyer sur le bouton
        // 3. Set a ThermostatSetCommand with the input temperature and press the button
        // 4. Définir un 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

Entraînez-vous par vous-même : Compilateur Java en ligne