Kommando-Entwurfsmuster¶
Kommando ist ein weiteres Entwurfsmuster, das durch die Verwendung von Funktionen, die als Argumente übergeben werden, vereinfacht werden kann:
Das Ziel des Kommando-Entwurfsmusters ist es, ein Objekt, das eine Operation
aufruft vom Receiver-Objekt zu entkoppeln, das die Operation
implementiert. Im Beispiel aus dem Entwurfsmuster-Buch ist jedes
Caller-Objekt ein Menüpunkt in einer grafischen Anwendung, und die
Receiver-Objekte sind das zu bearbeitende Dokument oder die Anwendung
selbst. Hierzu wird ein Command-Objekt zwischen die beiden gesetzt, das
eine Schnittstelle mit einer einzigen Methode implementiert, die eine Methode im
Receiver aufruft, um die gewünschte Operation durchzuführen. Auf diese
Weise muss das Caller-Objekt das Interface des Receiver nicht
kennen, und verschiedene Empfänger können durch verschiedene
Command-Unterklassen angepasst werden. Caller wird mit einem
ConcreteCommand-Befehl konfiguriert und ruft dessen
execute()-Methode auf, um ihn auszuführen.
Command sind ein objektorientierter Ersatz für Callbacks. [1]
Die Frage ist nun, ob wir in Python wirklich einen solchen objektorientierten
Ersatz für Callbacks brauchen? Können wir stattdessen nicht dem Caller
einfach eine Funktion geben? Anstatt also Command.execute() aufzurufen,
könnte der Caller einfach command() aufrufen. Dabei kann
Command eine Klasse sein, die __call__() implementiert und
Instanzen von Command wären dann sog. callables,
die jeweils eine Liste von Funktionen für zukünftige Aufrufe enthalten,
z.B.:
1class MacroCommand:
2 """A command that executes a list of command."""
3
4 def __init__(self, commands):
5 self.commands = list(commands)
6
7 def __call__(self):
8 for command in self.commands:
9 command()
- Zeilen 4–5
erstellt eine Liste aus den Befehlsargumenten und stellt sicher, dass sie iterierbar ist
- Zeile 7–8
erstellt eine lokale Kopie der Befehlsreferenzen in jeder
MacroCommand-Instanz. Wenn eine Instanz vonMacroCommandaufgerufen wird, wird jeder Befehl inself.commandsnacheinander aufgerufen.