Menu
Coddy logo textTech

Command-Muster

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 94 von 110.

Das Command-Pattern kapselt eine Anfrage als Objekt und ermöglicht es Ihnen so, Clients mit verschiedenen Anfragen zu parametrisieren, Operationen in eine Warteschlange zu stellen oder eine Rückgängig-Funktionalität zu unterstützen. Anstatt eine Methode direkt aufzurufen, kapseln Sie die Aktion in einem Command-Objekt, das gespeichert, weitergegeben oder später ausgeführt werden kann.

Das Muster umfasst drei Schlüsselkomponenten: eine Command-Schnittstelle mit einer execute-Methode, konkrete Befehle (Concrete Commands), die spezifische Aktionen implementieren, und einen Receiver, der die eigentliche Arbeit verrichtet. Ein optionaler Invoker löst Befehle aus, ohne zu wissen, was sie tun:

abstract class Command {
  void execute();
}

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class TurnOffCommand implements Command {
  final Light light;
  TurnOffCommand(this.light);

  @override
  void execute() => light.turnOff();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // Licht ist AN

  remote.setCommand(TurnOffCommand(light));
  remote.pressButton();  // Licht ist AUS
}

Die RemoteControl weiß nichts über Lichter – sie führt einfach den Befehl aus, den sie erhält. Diese Entkopplung macht es einfach, neue Befehle hinzuzufügen, ohne den Invoker zu modifizieren. Das Command-Pattern ist ideal für die Implementierung von Undo/Redo-Systemen, Task-Queues oder Makro-Aufzeichnungen, bei denen Aktionen als First-Class-Objekte behandelt werden müssen.

challenge icon

Aufgabe

Einfach

Lass uns ein Texteditor-Befehlssystem mit dem Command-Pattern bauen! Du wirst ein System erstellen, das Textoperationen als Befehlsobjekte kapselt, sodass ein Editor verschiedene Aktionen ausführen kann, ohne die Details jeder Operation zu kennen. Dies ist ein klassischer Anwendungsfall für das Command-Pattern – stell es dir wie ein Undo/Redo-System vor, bei dem jede Aktion als Objekt gespeichert wird.

Du wirst deinen Code in zwei Dateien organisieren:

  • commands.dart: Erstelle hier dein Befehlssystem. Beginne mit einer abstrakten Klasse Command, die eine execute()-Methode deklariert. Erstelle dann eine TextDocument-Klasse (den Empfänger), die ein String content-Feld (anfänglich leer) hält und drei Methoden besitzt:
    • append(String text) – fügt Text am Ende des Inhalts hinzu
    • clear() – setzt den Inhalt auf einen leeren String
    • show() – gibt Document: [content] aus
    Implementiere nun drei konkrete Befehle, die mit einem TextDocument arbeiten:
    • AppendCommand – nimmt ein Dokument und Text in seinem Konstruktor entgegen und hängt den Text an, wenn er ausgeführt wird
    • ClearCommand – nimmt ein Dokument in seinem Konstruktor entgegen und leert es, wenn er ausgeführt wird
    • ShowCommand – nimmt ein Dokument in seinem Konstruktor entgegen und zeigt dessen Inhalt an, wenn er ausgeführt wird
    Erstelle schließlich eine TextEditor-Klasse (den Aufrufer), die eine Liste von Befehlen speichert. Sie sollte eine addCommand(Command command)-Methode haben, um Befehle in die Warteschlange zu stellen, und eine runAll()-Methode, die alle in der Warteschlange befindlichen Befehle der Reihe nach ausführt.
  • main.dart: Importiere deine Befehlsdatei und demonstriere das Command-Pattern. Erstelle ein TextDocument und einen TextEditor. Stelle die folgenden Befehle nacheinander in die Warteschlange: hänge Hello an, hänge World an, zeige das Dokument an, hänge ! an, zeige es erneut an, leere das Dokument und zeige es ein letztes Mal an. Führe dann alle in der Warteschlange befindlichen Befehle aus.

Beachte, dass der TextEditor nichts über das Anhängen, Leeren oder Anzeigen weiß – er führt einfach die Befehle aus, die ihm gegeben werden. Diese Entkopplung ist der Kern des Command-Patterns!

Erwartete Ausgabe:

Document: Hello World
Document: Hello World!
Document: 

Probier es selbst

import 'commands.dart';

void main() {
  // TODO: Erstelle eine TextDocument-Instanz

  // TODO: Erstelle eine TextEditor-Instanz

  // TODO: Reihe die folgenden Befehle in dieser Reihenfolge ein:
  // 1. Hänge "Hello" an
  // 2. Hänge " World" an
  // 3. Zeige das Dokument an
  // 4. Hänge "!" an
  // 5. Zeige das Dokument erneut an
  // 6. Leere das Dokument
  // 7. Zeige das Dokument ein letztes Mal an

  // TODO: Führe alle eingereihten Befehle aus
}
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