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 ONDas 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.
Aufgabe
EinfachErstellen 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 dasCommand-Interface, das alle Gerätebefehle implementieren werden. Es soll eine einzige Methodeexecute()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 MethodenpowerOn(), dieTV is now ONausgibt,powerOff(), dieTV is now OFFausgibt, undsetChannel(int channel), dieTV channel set to [channel]ausgibt.Thermostat– verfügt über die MethodensetTemperature(int temp), dieThermostat set to [temp] degreesausgibt, undturnOff(), dieThermostat turned OFFausgibt.Commands.java: Erstelle konkrete Befehlsklassen, die Geräteoperationen kapseln:TVOnCommand– erhält in seinem Konstruktor einTelevision-Objekt und ruft bei der AusführungpowerOn()auf.TVOffCommand– erhält in seinem Konstruktor einTelevision-Objekt und ruft bei der AusführungpowerOff()auf.TVChannelCommand– erhält in seinem Konstruktor einTelevision-Objekt und einenint channel-Wert und ruft bei der AusführungsetChannel()mit diesem Kanal auf.ThermostatSetCommand– erhält in seinem Konstruktor einThermostat-Objekt und einenint temperature-Wert und ruft bei der AusführungsetTemperature()mit diesem Wert auf.Main.java: Erstelle eineRemoteControl-Klasse (den Invoker), die über eine MethodesetCommand(Command cmd)zum Speichern eines Befehls undpressButton()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 einThermostat-Objekt. Erstelle eineRemoteControlund demonstriere das Command Pattern, indem du:- einen
TVOnCommandsetzt und die Taste drückst - einen
TVChannelCommandmit deinem Eingabekanal setzt und die Taste drückst - einen
ThermostatSetCommandmit deiner Eingabetemperatur setzt und die Taste drückst - einen
TVOffCommandsetzt und die Taste drückst
- einen
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 OFFBeachte, 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();
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenFelder (Attribute)KonstruktormethodeÜberladen von KonstruktorenRückblick – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbung (extends)Das Schlüsselwort superÜberschreiben von Methoden (@Override)KonstruktorverkettungDie Object-KlasseEinfach- und mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenRückblick – Mitarbeiterhierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-SchnittstelleRückblick – Benutzerdefinierte Sortierung2Zugriffsmodifikatoren & Kapselung
Übersicht der ZugriffsebenenGetter- und Setter-MethodenInformationsverbergungDas Schlüsselwort finalRückblick – Bankkontoverwaltung5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, verschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Versiegelte Klassen (Java 17+)11Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBuilder-MusterObserver-MusterStrategie-Muster14Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungsdienst3Klassen-Props & statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Wiederholung – Counter & Utility6Schnittstellen & abstrakte Klassen
Einführung in InterfacesInterfaces implementierenMehrere Interfaces implementierenDefault & Static in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesRückblick – Zahlungssystem9Generics
Einführung in GenericsGenerische KlassenGenerische MethodenGebundene TypparameterWildcards (?, extends, super)Rückblick – Generischer Container12Entwurfsmuster Teil 2
BefehlsmusterAdaptermusterDekorierermusterSchablonenmethodenmusterZustandsmusterKompositmusterIteratormusterÜbe selbstständig: Online-Java-Compiler