Menu
Coddy logo textTech

Command-Muster

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 70 von 87.

Das Command-Pattern ist ein Verhaltensmuster, das eine Anfrage in ein eigenständiges Objekt umwandelt, das alle Informationen über die Anfrage enthält. Diese Transformation ermöglicht es Ihnen, Anfragen als Methodenargumente zu übergeben, die Ausführung einer Anfrage zu verzögern oder in eine Warteschlange zu stellen und rückgängig machbare Operationen zu unterstützen.

Stellen Sie es sich wie ein Restaurant vor: Anstatt dem Koch direkt zu sagen, was er kochen soll, schreiben Sie Ihre Bestellung auf einen Zettel. Der Kellner (invoker) bringt den Zettel (command) in die Küche, wo er in eine Warteschlange eingereiht, priorisiert oder sogar storniert werden kann. Das Muster entkoppelt das Objekt, das die Operation aufruft, von demjenigen, das sie ausführt.

Das Muster besteht aus vier Schlüsselkomponenten: einem Command-Interface, das die execute-Methode deklariert, ConcreteCommand-Klassen, die spezifische Aktionen implementieren, einem Receiver, der die eigentliche Arbeit verrichtet, und einem Invoker, der Befehle auslöst:

interface Command {
    void execute();
}
class Light {  // Empfänger
    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 {  // Invoker
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Der Aufrufer weiß nicht, welche Aktion ausgeführt wird – er ruft einfach nur execute() auf:

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

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Ausgabe: Licht ist AN

Das Command-Pattern glänzt, wenn Sie Operationen in eine Warteschlange stellen, eine Rückgängig/Wiederholen-Funktionalität implementieren oder Aufgaben für eine spätere Ausführung planen müssen. Jeder Befehl kapselt alles ein, was zur Ausführung einer Aktion erforderlich ist, wodurch Ihr System flexibler und erweiterbarer wird.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein intelligentes Hausautomationssystem mit dem Command Pattern bauen! Sie werden ein System erstellen, in dem verschiedene Heimgeräte über Befehle gesteuert werden können, was es ermöglicht, Aktionen in eine Warteschlange zu stellen, auszuführen und sogar für die spätere Verwendung zu speichern – genau wie eine Universalfernbedienung, die nicht wissen muss, wie jedes Gerät intern funktioniert.

Sie werden Ihren Code über vier Dateien organisieren:

  • Command.java: Definieren Sie das Command-Interface, das alle Gerätebefehle implementieren werden. Es sollte eine einzige Methode execute() deklarieren, die die Aktion des Befehls ausführt.
  • Devices.java: Erstellen Sie zwei Empfänger-Klassen (Receiver), die Smart-Home-Geräte repräsentieren:

    Television - hat die Methoden powerOn(), die "TV is now ON" ausgibt, powerOff(), die "TV is now OFF" ausgibt, und setChannel(int channel), die "TV channel set to " + channel ausgibt.

    Thermostat - hat die Methoden setTemperature(int temp), die "Thermostat set to " + temp + " degrees" ausgibt, und turnOff(), die "Thermostat turned OFF" ausgibt.

  • Commands.java: Erstellen Sie konkrete Befehlsklassen, die die Geräteoperationen kapseln:

    TVOnCommand - nimmt ein Television-Objekt in seinem Konstruktor entgegen und ruft powerOn() auf, wenn es ausgeführt wird.

    TVOffCommand - nimmt ein Television-Objekt in seinem Konstruktor entgegen und ruft powerOff() auf, wenn es ausgeführt wird.

    TVChannelCommand - nimmt ein Television-Objekt und ein int channel in seinem Konstruktor entgegen und ruft setChannel() mit diesem Kanal auf, wenn es ausgeführt wird.

    ThermostatSetCommand - nimmt ein Thermostat-Objekt und eine int temperature in seinem Konstruktor entgegen und ruft setTemperature() mit diesem Wert auf, wenn es ausgeführt wird.

  • Main.java: Erstellen Sie eine RemoteControl-Klasse (den Invoker), die eine Methode setCommand(Command cmd) zum Speichern eines Befehls und pressButton() zum Ausführen des gespeicherten Befehls besitzt.

    In Ihrer Main-Methode erhalten Sie zwei Eingaben: eine TV-Kanalnummer (Integer) und eine Thermostat-Temperatur (Integer).

    Erstellen Sie ein Television- und ein Thermostat-Objekt. Erstellen Sie eine RemoteControl und demonstrieren Sie das Command Pattern durch:

    1. Setzen eines TVOnCommand und Drücken der Taste
    2. Setzen eines TVChannelCommand mit Ihrem eingegebenen Kanal und Drücken der Taste
    3. Setzen eines ThermostatSetCommand mit Ihrer eingegebenen Temperatur und Drücken der Taste
    4. Setzen eines TVOffCommand und Drücken der Taste

Sie erhalten zwei Eingaben in dieser Reihenfolge: den TV-Kanal (Integer) und die Thermostat-Temperatur (Integer).

Zum Beispiel, bei den Eingaben 5 und 72, wäre Ihre Ausgabe:

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

Beachten Sie, wie die RemoteControl niemals direkt mit den Geräten interagiert – sie kennt nur das Command-Interface. Jeder Befehl kapselt alles, was zur Ausführung seiner Aktion benötigt wird, was es einfach macht, neue Geräte und Befehle hinzuzufügen, ohne den Invoker zu ändern!

Probier es selbst

import java.util.Scanner;

// TODO: Erstelle die Klasse RemoteControl (den Invoker) mit:
// - der Methode setCommand(Command cmd), um einen Befehl zu speichern
// - der Methode pressButton(), um den gespeicherten Befehl auszuführen

class RemoteControl {
    // TODO: Implementiere RemoteControl
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Erstelle einen Television und einen Thermostat
        
        // TODO: Erstelle eine RemoteControl
        
        // TODO: Demonstriere das Command Pattern:
        // 1. Setze einen TVOnCommand und drücke den Knopf
        // 2. Setze einen TVChannelCommand mit dem eingegebenen Kanal und drücke den Knopf
        // 3. Setze einen ThermostatSetCommand mit der eingegebenen Temperatur und drücke den Knopf
        // 4. Setze einen TVOffCommand und drücke den Knopf
        
        scanner.close();
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung