Kommando (Entwurfsmuster)

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

In der objektorientierten Programmierung ist Kommando (auch Befehl; englisch command) ein Entwurfsmuster, das zur Kategorie der Verhaltensmuster (engl. behavioral design patterns) gehört. In diesem Entwurfsmuster kapselt das Kommando-Objekt einen Befehl, um es so zu ermöglichen, Operationen in eine Warteschlange zu stellen, Logbucheinträge zu führen und Operationen rückgängig zu machen.[1] Es ist eines der GoF-Muster.

Verwendung[Bearbeiten]

Wenn z. B. eine Schaltfläche in einer GUI mit einer Aktion verknüpft werden soll, dient das Kommando dazu, die auszuführende Aktion zu parametrisieren. Es stellt somit die objektorientierte Entsprechung zu den Rückruffunktionen (callback function) dar. Dabei können das Erstellen des Kommandos und die tatsächliche Ausführung zu verschiedenen Zeiten oder in einem anderen Kontext (Thread, Prozess, Rechner) stattfinden.

Implementierung eines Rückgängig-Mechanismus (undo): Bei jeder Ausführung werden die zur Umkehrung nötigen Daten im 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.

Akteure[Bearbeiten]

UML-Klassendiagramm

Der Befehl ist die Basisklasse aller Kommandos. Ein Konkreter Befehl speichert den zum Ausführen nötigen Zustand, darunter typischerweise auch einen Verweis auf den Empfänger und implementiert die Befehlsschnittstelle.

Der Klient erzeugt einen konkreten Befehl und versieht ihn mit einem Verweis auf den Empfänger und allen anderen nötigen Informationen. Er gibt dem Aufrufer eine Referenz auf den konkreten Befehl.

Der Aufrufer besitzt einen oder mehrere Verweise auf Befehle und fordert diese bei Bedarf auf, ihre 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. Der konkrete Befehl ruft Methoden des Empfängerobjektes auf, um seine Aktion auszuführen.

Vor- & Nachteile[Bearbeiten]

Auslösender und Ausführender sind entkoppelt. Befehlsobjekte können wie andere Objekte auch manipuliert werden (Verändern, Filtern, Zwischenspeichern, …). Befehlsobjekte können zu komplexen Befehlen kombiniert werden (Makros, realisiert als Kompositum).

Da für jedes Kommando eine neue Klasse benötigt wird, kann deren Anzahl schnell groß und die Implementierung damit unübersichtlich werden.

Beispiel[Bearbeiten]

Die Verknüpfung von GUI-Elementen stellt ein einfaches Beispiel mit Schaltflächen oder Menüpunkten dar:

  • 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)
Beispiel in F#
// Units
[<Measure>] type km
[<Measure>] type h
[<Measure>] type rad
[<Measure>] type degree
let convertDegreeToRad (angle : float<degree>) = Math.PI * angle / 180.0
 
// Commands
type Command = Command of (Rover -> unit)
let AccelerateCommand = Command(fun rover -> rover.Accelerate(0.5<km/h>))
let BreakCommand = Command(fun rover -> rover.Accelerate(-1.0<km/h>))
let TurnLeftCommand = Command(fun rover -> rover.Rotate(convertDegreeToRad -5.0<degree>))
let TurnRightCommand = Command(fun rover -> rover.Rotate(convertDegreeToRad 5.0<degree>))
 
type MarsRoverCommand = 
   | AccelerateCommand
   | BreakCommand
   | TurnLeftCommand
   | TurnRightCommand
Beispiel in C#
static class UnitConversions
{
   public static float ConvertDegreeToRad(float angle)
   {
      return Math.PI * angle / 180.0;
   }
}
 
public interface ICommand
{
   void Execute();
}
 
public abstract class MarsRoverCommand : ICommand
{
   protected MarsRover Rover { get; set; }
 
   public MarsRoverCommand(MarsRover rover)
   {
      Rover = rover;
   }
 
   public virtual void Execute();
}
 
public class AccelerateCommand : MarsRoverCommand
{
   public AccelerateCommand(MarsRover rover) : base(rover)
   {
   }
 
   public override void Execute()
   {
      Rover.Accelerate(0.5f);
   } 
}
 
public class BreakCommand : MarsRoverCommand
{
   public BreakCommand(MarsRover rover) : base(rover)
   {
   }
 
   public override void Execute()
   {
      Rover.Accelerate(-1.0);
   } 
}
 
public class TurnLeftCommand : MarsRoverCommand
{
   public TurnLeftCommand(MarsRover rover) : base(rover)
   {
   }
 
   public override void Execute()
   {
      Rover.Rotate(UnitConversions.ConvertDegreeToRad(5.0));
   } 
}
 
public class TurnRightCommand : MarsRoverCommand
{
   public TurnRightCommand(MarsRover rover) : base(rover)
   {
   }
 
   public override void Execute()
   {
      Rover.Rotate(UnitConversions.ConvertDegreeToRad(5.0));
   } 
}

Weblinks[Bearbeiten]

 Commons: Kommando (Entwurfsmuster) – Sammlung von Bildern, Videos und Audiodateien
 Wikibooks: Muster: Command – Lern- und Lehrmaterialien

Einzelnachweise[Bearbeiten]

  1.  Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Entwurfsmuster. 5 Auflage. Addison-Wesley, 1996, ISBN 3-8273-1862-9, S. 287.