Menu
Coddy logo textTech

Strategy-Muster

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

Das Strategy Pattern (Strategiemuster) ist ein Verhaltensmuster, das es Ihnen ermöglicht, eine Familie von Algorithmen zu definieren, jeden einzelnen in einer eigenen Klasse zu kapseln und sie zur Laufzeit austauschbar zu machen. Das Objekt, das die Strategie verwendet, muss nicht wissen, welcher Algorithmus gerade ausgeführt wird.

Stellen Sie sich einen Warenkorb vor, der verschiedene Rabattstrategien anwenden kann. Anstatt die Rabattlogik fest mit Bedingungen zu codieren, definieren Sie jeden Rabatt als eine separate Klasse:

<?php
interface DiscountStrategy {
    public function calculate(float $total): float;
}

class NoDiscount implements DiscountStrategy {
    public function calculate(float $total): float {
        return $total;
    }
}

class PercentageDiscount implements DiscountStrategy {
    public function __construct(private int $percent) {}
    
    public function calculate(float $total): float {
        return $total - ($total * $this->percent / 100);
    }
}

class FixedDiscount implements DiscountStrategy {
    public function __construct(private float $amount) {}
    
    public function calculate(float $total): float {
        return max(0, $total - $this->amount);
    }
}

Die Kontext-Klasse akzeptiert jede Strategie und delegiert die Berechnung:

<?php
class ShoppingCart {
    public function __construct(private DiscountStrategy $discount) {}
    
    public function setDiscount(DiscountStrategy $discount): void {
        $this->discount = $discount;
    }
    
    public function checkout(float $total): float {
        return $this->discount->calculate($total);
    }
}

$cart = new ShoppingCart(new NoDiscount());
echo $cart->checkout(100) . "\n";

$cart->setDiscount(new PercentageDiscount(20));
echo $cart->checkout(100);

Ausgabe:

100
80

Das Strategy-Pattern glänzt, wenn Sie mehrere Möglichkeiten haben, eine Operation auszuführen, und zwischen ihnen wechseln möchten, ohne die Klasse zu ändern, die sie verwendet. Das Hinzufügen eines neuen Rabatttyps bedeutet das Erstellen einer neuen Klasse, ohne den bestehenden Code anzurühren.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Versandkostenrechner mit dem Strategy Pattern erstellen. Verschiedene Versandarten haben unterschiedliche Preisregeln — Standardversand berechnet eine Pauschale, Expressversand fügt einen Prozentsatz hinzu und Übernachtversand kombiniert beides. Das Strategy Pattern ermöglicht es Ihnen, diese Berechnungen auszutauschen, ohne den Code zu ändern, der sie verwendet.

Sie werden Ihren Code über vier Dateien organisieren:

  • ShippingStrategy.php — Erstellen Sie ein ShippingStrategy Interface, das den Vertrag für alle Versandmethoden definiert. Es sollte eine Methode calculate(float $weight): float haben, die das Paketgewicht entgegennimmt und die Versandkosten zurückgibt.
  • ShippingMethods.php — Binden Sie die ShippingStrategy-Datei ein und erstellen Sie drei Klassen, die das Interface implementieren:
    • StandardShipping — Berechnet eine Pauschale von $5.00 unabhängig vom Gewicht
    • ExpressShipping — Berechnet $2.00 pro Kilogramm (Gewicht multipliziert mit 2)
    • OvernightShipping — Berechnet eine Grundgebühr von $10.00 plus $3.00 pro Kilogramm
  • ShippingCalculator.php — Binden Sie die ShippingStrategy-Datei ein und erstellen Sie eine ShippingCalculator Klasse, die als Kontext fungiert. Ihr Rechner sollte:
    • Eine ShippingStrategy in seinem Konstruktor akzeptieren (verwenden Sie Constructor Promotion)
    • Eine setStrategy(ShippingStrategy $strategy): void Methode haben, um die Versandmethode zur Laufzeit zu ändern
    • Eine calculateCost(float $weight): float Methode haben, die an die aktuelle Strategie delegiert
  • main.php — Binden Sie die Dateien ShippingMethods und ShippingCalculator ein. Sie erhalten zwei Eingaben: einen Versandtyp ("standard", "express" oder "overnight") und ein Paketgewicht.

    Erstellen Sie einen ShippingCalculator, beginnend mit StandardShipping. Verwenden Sie basierend auf der Eingabe des Versandtyps setStrategy(), um zur entsprechenden Versandmethode zu wechseln. Berechnen Sie dann die Kosten für das angegebene Gewicht und geben Sie das Ergebnis auf zwei Dezimalstellen formatiert aus.

    Die Ausgabe sollte sein: Shipping cost: $[cost]

Diese Herausforderung zeigt, wie das Strategy Pattern Ihr Versandsystem flexibel macht — das Hinzufügen einer neuen Versandmethode wie SameDayShipping erfordert nur das Erstellen einer neuen Klasse, die das Interface implementiert, ohne den Rechner oder bestehende Versandmethoden anzupassen.

Probier es selbst

<?php
require_once 'ShippingMethods.php';
require_once 'ShippingCalculator.php';

// Eingabe lesen
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));

// TODO: Erstelle einen ShippingCalculator beginnend mit StandardShipping

// TODO: Basierend auf der Eingabe der Versandart ("standard", "express" oder "overnight"),
// verwende setStrategy(), um zur entsprechenden Versandmethode zu wechseln

// TODO: Berechne die Kosten für das angegebene Gewicht

// TODO: Gib das Ergebnis auf zwei Dezimalstellen formatiert aus
// Ausgabeformat: Shipping cost: $[cost]

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