Design pattern

Command

(Action, Transaction)

Design pattern

Command

Command

(Action, Transaction)

Command Design Pattern

Kapselung von Anfragen als eigenständige Objekte

  • GoF Pattern
  • Entkopplung
  • Undo / Redo

Inhaltsverzeichnis

  1. Was ist das Command Pattern?
  2. Wann wird es verwendet?
  3. Kernkomponenten
  4. Funktionsweise
  5. Praxisbeispiele
  6. Undo / Redo
  7. Vorteile & Nachteile
  8. Best Practices

1. Was ist das Command Pattern?

Das Command Pattern ist ein Verhaltensmuster, das eine Anfrage als Objekt kapselt. Dadurch können Aktionen flexibel übergeben, gespeichert, protokolliert oder später ausgeführt werden.

Statt einen Methodenaufruf direkt auszuführen, wird daraus ein eigenes Objekt, das alle Informationen über die Aktion enthält.

Grundidee

  • Trennung: Aufrufer und Ausführer einer Aktion werden entkoppelt
  • Kapselung: Methode, Parameter und Empfänger werden in einem Objekt gespeichert
  • Flexibilität: Aktionen können übergeben, verzögert oder rückgängig gemacht werden

2. Wann verwendet man das Command Pattern?

  • GUI-Komponenten: Buttons, Menüs, Toolbar-Aktionen
  • Job Queues: Aufgaben später oder asynchron ausführen
  • Undo / Redo: Aktionen rückgängig machen
  • Logging: Operationen speichern und erneut abspielen

Beispiele für den Einsatz

  • Texteditoren mit Copy, Paste, Save, Undo
  • Warteschlangen wie RabbitMQ oder Background Jobs
  • Grafikprogramme mit Rückgängig-Funktion
  • Smart-Home-Steuerungen und Fernbedienungen

3. Kernkomponenten

  1. Command – definiert die Schnittstelle, meist execute()
  2. Concrete Command – konkrete Implementierung einer Aktion
  3. Receiver – führt die eigentliche Geschäftslogik aus
  4. Invoker – löst die Command aus
  5. Client – erstellt und verbindet alle Objekte

Die Rollen im Überblick

  • Command: gemeinsamer Vertrag für alle Befehle
  • Concrete Command: kennt Receiver und konkrete Aktion
  • Receiver: enthält die eigentliche Logik
  • Invoker: startet die Ausführung, ohne Details zu kennen
  • Client: verdrahtet das System

4. Funktionsweise

  1. Der Client erstellt den Receiver
  2. Der Client erstellt ein Concrete Command mit dem Receiver
  3. Der Client übergibt das Command an den Invoker
  4. Der Invoker ruft execute() auf
  5. Das Command delegiert die Arbeit an den Receiver

Wichtige Erkenntnis

Der Invoker kennt den Receiver nicht direkt. Er kennt nur das Command Interface.

Genau diese Entkopplung macht das Pattern so flexibel und gut erweiterbar.

5. Praxisbeispiele

  • GUI-Buttons: Jeder Button führt ein Command aus
  • Texteditoren: Jede Änderung ist ein Command
  • Datenbanktransaktionen: Operationen können gekapselt werden
  • Fernbedienungen: Ein Knopf steuert verschiedene Geräte

Restaurant-Beispiel

  • Kellner = Invoker
  • Bestellung = Command
  • Küche = Receiver

Der Kellner kocht nicht selbst, sondern gibt die Bestellung an die Küche weiter. Genau so delegiert der Invoker die Aktion an den Receiver.

6. Undo / Redo

Ein großer Vorteil des Command Patterns ist die Unterstützung von Undo und Redo.

  • Jede Aktion wird als Command gespeichert
  • Die Historie wird meist in Stacks verwaltet
  • Ein Command kann neben execute() auch undo() besitzen

Typischer Ablauf bei Undo / Redo

  1. Vor der Ausführung wird der relevante Zustand gespeichert
  2. Nach execute() landet das Command im Undo-Stack
  3. Bei Undo wird das letzte Command zurückgenommen
  4. Bei Redo wird es erneut ausgeführt

7. Vorteile

  • Lose Kopplung zwischen Sender und Empfänger
  • Erweiterbarkeit durch neue Commands ohne Änderungen am Kernsystem
  • Undo / Redo lässt sich gut integrieren
  • Queueing und Logging von Aktionen ist einfach möglich
  • Makro-Kommandos können mehrere Aktionen zusammenfassen

8. Nachteile

  • Es entstehen oft viele kleine Klassen
  • Für einfache Projekte kann das Pattern zu komplex sein
  • Undo erfordert sauberes Zustandsmanagement
  • Große Command-Historien können Speicher verbrauchen
  • Nicht jede Aktion mit Seiteneffekten ist leicht rückgängig zu machen

Best Practices

  • Jede Command sollte nur eine Aufgabe haben
  • Commands möglichst immutable gestalten
  • Factories oder Builder für komplexe Commands verwenden
  • Seiteneffekte klar dokumentieren
  • Ein Null Command vermeidet Null-Prüfungen

Einfaches Java-Beispiel

public interface Command {
    void execute();
    void undo();
}

Konkrete Commands implementieren dieses Interface und rufen die passende Methode des Receivers auf.

Fazit

Das Command Pattern kapselt Aktionen als Objekte und sorgt damit für Entkopplung, Erweiterbarkeit und Kontrolle.

  • Sender und Empfänger werden getrennt
  • Aktionen werden flexibel steuerbar
  • Undo, Redo, Logging und Queueing werden erleichtert

Vielen Dank!

Fragen?