Menu
Coddy logo textTech

Befehlsmuster

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

Das Command Pattern ist ein Verhaltensentwurfsmuster, das eine Anfrage in ein eigenständiges Objekt umwandelt, das alle Informationen über die Anfrage enthält. Diese Umwandlung ermöglicht es dir, Anfragen als Methodenargumente zu übergeben, die Ausführung einer Anfrage zu verzögern oder in eine Warteschlange einzureihen und rückgängig machbare Vorgänge zu unterstützen.

Stell es dir wie in einem Restaurant vor: Anstatt dem Koch direkt zu sagen, was er kochen soll, schreibst du deine Bestellung auf einen Zettel. Der Kellner (Invoker) bringt den Zettel (Befehl) 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 hat vier Hauptkomponenten: eine Command-Schnittstelle, die die execute-Methode deklariert, ConcreteCommand-Klassen, die bestimmte Aktionen implementieren, einen Receiver, der die eigentliche Arbeit ausführt, und einen 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 {  // Aufrufer
    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 execute() auf:

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

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

Das Command Pattern ist besonders geeignet, wenn du Vorgänge in eine Warteschlange stellen, eine Rückgängig-/Wiederholen-Funktion implementieren oder Aufgaben zur späteren Ausführung planen musst. Jeder Befehl kapselt alles, was zum Ausführen einer Aktion erforderlich ist, und macht dein System dadurch flexibler und erweiterbarer.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Smart-Home-Automatisierungssystem mithilfe des Command Patterns! Du erstellst ein System, in dem verschiedene Haushaltsgeräte über Befehle gesteuert werden können, sodass Aktionen in eine Warteschlange gestellt, ausgeführt und sogar zur späteren Verwendung gespeichert werden können – ähnlich wie bei einer Universalfernbedienung, die nicht wissen muss, wie die einzelnen Geräte intern funktionieren.

Du organisierst deinen Code über vier Dateien:

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

    Television – verfügt über 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 – verfügt über die Methoden setTemperature(int temp), die Thermostat set to [temp] degrees ausgibt, und turnOff(), die Thermostat turned OFF ausgibt.

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

    TVOnCommand – erhält in seinem Konstruktor ein Television-Objekt und ruft bei der Ausführung powerOn() auf.

    TVOffCommand – erhält in seinem Konstruktor ein Television-Objekt und ruft bei der Ausführung powerOff() auf.

    TVChannelCommand – erhält in seinem Konstruktor ein Television-Objekt und einen int channel-Wert und ruft bei der Ausführung setChannel() mit diesem Kanal auf.

    ThermostatSetCommand – erhält in seinem Konstruktor ein Thermostat-Objekt und einen int temperature-Wert und ruft bei der Ausführung setTemperature() mit diesem Wert auf.

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

    In deiner main-Methode erhältst du zwei Eingaben: eine TV-Kanalnummer (Ganzzahl) und eine Thermostattemperatur (Ganzzahl).

    Erstelle ein Television- und ein Thermostat-Objekt. Erstelle eine RemoteControl und demonstriere das Command Pattern, indem du:

    1. einen TVOnCommand setzt und die Taste drückst
    2. einen TVChannelCommand mit deinem Eingabekanal setzt und die Taste drückst
    3. einen ThermostatSetCommand mit deiner Eingabetemperatur setzt und die Taste drückst
    4. einen TVOffCommand setzt und die Taste drückst

Du erhältst zwei Eingaben in dieser Reihenfolge: den TV-Kanal (Ganzzahl) und die Thermostattemperatur (Ganzzahl).

Beispielsweise würde deine Ausgabe bei den Eingaben 5 und 72 folgendermaßen aussehen:

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

Beachte, dass die RemoteControl niemals direkt mit den Geräten interagiert. Sie kennt nur das Command-Interface. Jeder Befehl kapselt alles, was für die Ausführung seiner Aktion erforderlich ist. Dadurch lassen sich neue Geräte und Befehle einfach hinzufügen, ohne den Invoker ändern zu müssen!

Probier es selbst

import java.util.Scanner;

// TODO: Erstelle die RemoteControl-Klasse (den Invoker) mit:
// - setCommand(Command cmd)-Methode zum Speichern eines Befehls
// - pressButton()-Methode zum Ausführen des gespeicherten Befehls

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 ein Television und ein Thermostat
        
        // TODO: Erstelle ein RemoteControl
        
        // TODO: Demonstriere das Command Pattern:
        // 1. Setze ein TVOnCommand und drücke den Button
        // 2. Setze ein TVChannelCommand mit dem Eingabekanal und drücke den Button
        // 3. Set a ThermostatSetCommand with the input temperature and press the button
        // 4. Setze ein TVOffCommand und drücke den Button
        
        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

Übe selbstständig: Online-Java-Compiler