Menu
Coddy logo textTech

Befehlsmuster

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 75 von 91.

Das Command Pattern ist ein Verhaltensentwurfsmuster, das eine Anfrage in ein eigenständiges Objekt umwandelt, das alle Informationen über die Anfrage enthält. Diese Umwandlung ermöglicht es dir, Anfragen als Methodenargumente zu übergeben, die Ausführung einer Anfrage zu verzögern oder in eine Warteschlange zu stellen und rückgängig machbare Vorgänge zu unterstützen.

Stell dir ein Restaurant vor.

Wenn du Essen bestellst, schreibt der Kellner deine Bestellung auf einen Zettel (den Befehl), bringt ihn in die Küche, und der Koch führt ihn aus. Der Kellner muss nicht wissen, wie man kocht; er übermittelt einfach den Befehl.

Dadurch wird der Anforderer vom Ausführer entkoppelt.

Hier ist eine grundlegende Implementierung:

<?php
interface Command {
    public function execute(): string;
}
class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}
class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}
class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

Der Aufrufer löst Befehle aus, ohne zu wissen, was sie tun:

<?php
class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}
$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

Ausgabe:

Light is ON
Light is OFF

Das Command-Muster eignet sich besonders gut, wenn du Vorgänge in eine Warteschlange stellen, eine Rückgängig-Funktion implementieren oder Aktionen protokollieren musst. Jeder Befehl ist in sich geschlossen, sodass du problemlos neue Befehle hinzufügen kannst, ohne vorhandenen Code zu ändern.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Texteditor-Befehlssystem unter Verwendung des Command Patterns. Texteditoren müssen häufig Vorgänge wie das Schreiben von Text, das Löschen von Text und das Rückgängigmachen von Aktionen unterstützen: Jeder Vorgang wird zu einem eigenständigen Befehlsobjekt, das über eine einheitliche Schnittstelle ausgeführt werden kann.

Du organisierst deinen Code auf vier Dateien verteilt:

  • Command.php: Definiere eine Command-Schnittstelle mit einer einzigen Methode execute(): string. Dadurch wird der Vertrag festgelegt, den alle Editorbefehle einhalten müssen.
  • TextEditor.php, Erstelle eine TextEditor-Klasse, die den Empfänger darstellt, also das Objekt, das die Arbeit tatsächlich ausführt. Dein Editor sollte:
    • den aktuellen Textinhalt speichern (beginne mit einer leeren Zeichenkette)
    • eine Methode write(string $text): string besitzen, die Text an den Inhalt anhängt und "Written: [text]" zurückgibt
    • eine Methode clear(): string besitzen, die den Inhalt leert und "Content cleared" zurückgibt
    • eine Methode getContent(): string besitzen, die den aktuellen Inhalt zurückgibt
  • Commands.php: Binde die Dateien Command und TextEditor ein. Erstelle zwei Befehlsklassen, die die Command-Schnittstelle implementieren:
    • WriteCommand: Nimmt in seinem Konstruktor einen TextEditor und eine Textzeichenkette entgegen. Seine Methode execute() ruft die Methode write() des Editors auf und gibt das Ergebnis zurück.
    • ClearCommand: Nimmt in seinem Konstruktor einen TextEditor entgegen. Seine Methode execute() ruft die Methode clear() des Editors auf und gibt das Ergebnis zurück.
  • main.php: Binde die Commands-Datei ein. Du erhältst zwei Eingaben: einen Befehlstyp ("write" oder "clear") und eine Textzeichenkette (wird nur für Schreibbefehle verwendet).

    Erstelle eine TextEditor-Instanz. Erstelle abhängig vom Befehlstyp das entsprechende Befehlsobjekt. Erstelle anschließend eine Invoker-Funktion oder einen einfachen Mechanismus, der execute() für den Befehl aufruft und das Ergebnis ausgibt.

    Gib in einer neuen Zeile den aktuellen Inhalt des Editors in diesem Format aus: Content: [content] (falls der Inhalt leer ist, gib einfach Content: aus, ohne etwas nach dem Leerzeichen).

Diese Aufgabe zeigt, wie das Command Pattern jeden Vorgang als Objekt kapselt. Der Invoker muss nicht wissen, ob er einen Schreib- oder Löschbefehl ausführt. Er ruft einfach execute() auf und überlässt dem Befehl die Details.

Probier es selbst

<?php

require_once 'Commands.php';

// Eingabe lesen
$commandType = trim(fgets(STDIN)); // "write" oder "clear"
$text = trim(fgets(STDIN));         // Text für den write-Befehl

// TODO: Erstelle eine TextEditor-Instanz

// TODO: Basierend auf dem Befehlstyp erstelle das passende Befehlsobjekt
// - Wenn "write", erstelle einen WriteCommand mit dem Editor und dem Text
// - Wenn "clear", erstelle einen ClearCommand mit dem Editor

// TODO: Erstelle einen Invoker-Mechanismus, der execute() auf dem Befehl aufruft
// und das Ergebnis ausgibt

// TODO: Gib den aktuellen Inhalt des Editors im Format aus: "Content: [content]"
// (wenn leer, gib einfach "Content: " aus mit nichts nach dem Leerzeichen)

?>
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

Übe selbstständig: Online-PHP-Compiler