Muster: Command
Aus Wikibooks
Das Kommando oder der Befehl (engl. Command) ist ein Verhaltensmuster (Behavioral Patterns). Es dient zum Kapseln von Anfragen als Kommando-Objekte, um damit Empfänger zu parametrisieren. Anfragen können dabei in Warteschlangen gestellt, aufgezeichnet und später ggf. auch wieder rückgängig gemacht werden.
Auch bekannt als: Aktion, Transaktion (Action, Transaction)
[Bearbeiten] Verwendung
- Objekte sollen mit einer auszuführenden Aktion, dem Befehl, parametrisiert werden. Das ist die objektoriertierte Entsprechung zu Rückruffunktionen (eng. callback function).
- (z.B. eine Schaltfläche in einer GUI soll mit einer Aktion verknüpft werden)
- Befehle, also auszuführende Aktionen, werden in einzelne Objekte gekapselt. Dies folgt dem objektorientierten Prinzip der Kapselung des Veränderbaren.
- Das Erstellen des Befehls und das tatsächliche Ausführen finden zu verschiedenen Zeiten oder in einem anderen Kontext (Thread, Prozess, Rechner) statt.
- Da Befehle in Objekten gekapselt sind, können sie gespeichert, herumgereicht, gruppiert oder modifiziert werden. Dies erlaubt eine Reihe von interessanten Anwendungsmöglichkeiten, z.B.
- Implementation eines Rückgängig-Mechanismus (Undo). Bei jeder Ausführung werden die zur Umkehrung nötigen Daten im Befehls-Objekt gespeichert und das Objekt selber auf einem Stapel gesichert. Um das Gegenteil Wiederherstellen (Redo) zu implementieren, genügt ein zweiter Stapel für die rückgängig gemachten Befehle.
- Implementation einer Warteschlange, bei der die Befehle nacheinander abgearbeitet werden. Dabei sind die Befehle lose an die ausführende Einheit gekoppelt, so dass ein Austauschen, Ändern etc. zur Laufzeit möglich ist.
- Implementation von Logging von Befehlen und einer Wiederherstellung nach einem Systemabsturz.
- Gruppierung von mehreren Befehlsobjekten in einem Makrobefehl, um verschiedene Aktivitäten gebündelt auszuführen.
[Bearbeiten] UML-Diagramm
[Bearbeiten] Akteure
- Befehl
- Basisklasse aller Befehle
- definiert die Schnittstelle zum Ausführen des Befehls
- Konkreter Befehl
- speichert den zum Ausführen nötigen Zustand, darunter typischerweise auch einen Verweis auf den Empfänger
- implementiert die Befehlsschnittstelle
- Klient
- erzeugt einen konkreten Befehl und versieht ihn mit einem Verweis auf den Empfänger und allen anderen nötigen Informationen
- gibt dem Aufrufer eine Referenz auf den konkreten Befehl
- Aufrufer
- besitzt einen oder mehrere Verweise auf Befehle
- fordert diese Befehle bei Bedarf auf, ihre Aktion auszuführen
- Empfänger
- Der konkrete Befehl ruft Methoden des Empfängerobjektes auf, um seine Aktion auszuführen.
- An den Empfänger werden keine besonderen Anforderungen gestellt. Er muss nichts über die anderen Akteure wissen. Somit kann jede Klasse als Empfänger dienen.
[Bearbeiten] Vorteile
- Auslösender und Ausführender sind entkoppelt.
- Ausführenden können zur Laufzeit dynamisch neue Befehle übergeben werden.
- Befehlsobjekte können wie andere Objekte auch manipuliert werden (Verändern, Filtern, Zwischenspeichern, etc.).
- Befehlsobjekte können zu komplexen Befehlen kombiniert werden (Makros, realisiert als Kompositum).
[Bearbeiten] Nachteile
- Es wird für jedes Kommando eine neue Klasse benötigt. Dies kann sehr schnell zu einer großen Menge von Klassen führen.
[Bearbeiten] Beispiel
Ein gutes Beispiel für das Befehlsmuster, ist die Verknüpfung von GUI-Elementen, wie Schaltflächen oder Menüpunkten, mit den entsprechenden Aktionen:
- Konkrete Befehle realisieren dann Aktionen wie Datei öffnen, Rückgängig oder Schreibmarke nach rechts
- Klienten sind die Applikation oder Dialoge.
- Aufrufer sind Schaltflächen, Menüpunkte oder Hotkeys.
- Empfänger sind die Applikation (Datei öffnen) oder das Dokument (Rückgängig, Einfügemarke nach rechts)
[Bearbeiten] Ideen hinter erweiterten Anwendungen
- Der Makro-Befehl:
- Ein Makro-Befehl gruppiert einen Menge von Aktionen und führt sie gemeinsam aus. Dabei sind die einzelnen Aktionen in den Befehlsobjekten gekapselt. Idee ist nun, in einem Makro-Befehlsobjekt mehrere Befehlsobjekte zu speichern und diesen in einer vorgegebenen Reihenfolge zu befehlen, die Aktionen auf dem ihnen zugeordnetem Empfängerobjekt auszuführen.
- Der Makro-Befehl implementiert ebenfalls die Schnittstelle "Abstrakter Befehl". Ergänzt wird der Makro-Befehl um eine Liste oder ein Array zur Speicherung einer Reihe von Befehlsobjekten. Bei der Initialisierung (oder später dynamisch zur Laufzeit) wird dem Makro-Befehl ein Array von Befehlsobjekten übergeben.
- In der Methode ausführen(), welche einen Befehl zu Abarbeitung der Aktionen bewegt, iteriert der Makro-Befehl durch das Befehlsarray und ruft für jedes der Befehlsobjekte die Methode ausführen() auf.
- Eine Rückgängig-Funktionalität kann auch hier einfach gewährleistet werden, indem der Makro-Befehl rückwärts durch das Befehlsarray iteriert und auf jedem gespeichertem Befehlsobjekt die rückgängig()-Methode aufruft, die den Zustand des Systems vor der letzten Ausführung der ausführen()-Methode wiederherstellt.
[Bearbeiten] Verwandte Entwurfsmuster
- Makro-Befehle können als Kompositum implementiert werden.
- Das Memento-Entwurfsmuster kann die Objektzustände speichern, um eine Rückgängigfunktion zu vereinfachen.

