Menu
Coddy logo textTech

Adaptermuster

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

Das Adapter Pattern ist ein strukturelles Entwurfsmuster, das es Objekten mit inkompatiblen Schnittstellen ermöglicht, zusammenzuarbeiten. Es fungiert als Brücke zwischen zwei Schnittstellen und übersetzt Aufrufe von einem Format in ein anderes.

Stell dir vor, du entwickelst eine Anwendung, die Zahlungen verarbeitet, und musst eine Zahlungsbibliothek eines Drittanbieters integrieren. Die Bibliothek funktioniert einwandfrei, aber ihre Schnittstelle entspricht nicht dem, was dein Code erwartet. Anstatt deine gesamte Anwendung umzuschreiben, erstellst du einen Adapter, der zwischen beiden vermittelt.

<?php
// Das Interface, das Ihre Anwendung erwartet
interface PaymentProcessor {
    public function pay(float $amount): string;
}

// Drittanbieter-Bibliothek mit einem anderen Interface
class StripeAPI {
    public function createCharge(int $cents, string $currency): string {
        return "Charged {$cents} {$currency} via Stripe";
    }
}

Der Adapter implementiert Ihre erwartete Schnittstelle und verwendet intern die Klasse eines Drittanbieters:

<?php
class StripeAdapter implements PaymentProcessor {
    public function __construct(private StripeAPI $stripe) {}
    
    public function pay(float $amount): string {
        $cents = (int)($amount * 100);
        return $this->stripe->createCharge($cents, 'USD');
    }
}

$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);

Ausgabe:

Charged 2999 USD via Stripe

Der Adapter rechnet Dollar in Cent um und ruft die entsprechende Methode auf. Dein Anwendungscode kennt nur PaymentProcessor und bleibt dabei angenehm uninformiert über die spezifischen Anforderungen von Stripe. Wenn du später zu einem anderen Zahlungsanbieter wechselst, erstellst du einfach einen neuen Adapter, ohne deinen bestehenden Code zu ändern.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Temperaturumrechnungssystem mit dem Adapter-Muster. Du hast einen älteren Temperatursensor, der Messwerte in Fahrenheit ausgibt, aber deine moderne Wetteranwendung erwartet alle Temperaturen in Celsius. Anstatt eines der beiden Systeme zu ändern, erstellst du einen Adapter, der die Lücke überbrückt.

Du wirst deinen Code auf vier Dateien verteilen:

  • TemperatureSensor.php: Definiere ein TemperatureSensor-Interface, das deine Wetteranwendung erwartet. Es sollte eine Methode getTemperature(): float besitzen, die die Temperatur in Celsius zurückgibt.
  • LegacySensor.php: Erstelle eine LegacySensor-Klasse, die die alte Hardware simuliert. Diese Klasse hat eine andere Schnittstelle als die, die deine Anwendung benötigt:
    • Sie nimmt in ihrem Konstruktor einen Fahrenheit-Messwert entgegen (verwende Konstruktor-Promotion)
    • Sie besitzt eine Methode readFahrenheit(): float, die den gespeicherten Fahrenheit-Wert zurückgibt
  • LegacySensorAdapter.php: Binde sowohl das TemperatureSensor-Interface als auch die LegacySensor-Klasse ein. Erstelle eine LegacySensorAdapter-Klasse, die TemperatureSensor implementiert und einen LegacySensor kapselt. Dein Adapter sollte:
    • In seinem Konstruktor einen LegacySensor akzeptieren
    • getTemperature() implementieren, indem er den Fahrenheit-Wert vom älteren Sensor liest und ihn mithilfe der Formel (fahrenheit - 32) * 5 / 9 in Celsius umrechnet
  • main.php: Binde die Datei LegacySensorAdapter ein. Du erhältst eine Eingabe: eine Temperatur in Fahrenheit.

    Erstelle mit der Eingabetemperatur einen LegacySensor und kapsle ihn anschließend in einen LegacySensorAdapter. Rufe getTemperature() für den Adapter auf und gib das Ergebnis auf zwei Dezimalstellen gerundet aus.

    Das Ausgabeformat sollte lauten: Temperature: [celsius]C

Diese Herausforderung zeigt, wie das Adapter-Muster es dir ermöglicht, inkompatible Schnittstellen zu integrieren, ohne bestehenden Code zu ändern. Deine Wetteranwendung arbeitet ausschließlich mit dem TemperatureSensor-Interface und weiß überhaupt nicht, dass die tatsächlichen Messwerte von einem älteren Fahrenheit-Sensor stammen.

Probier es selbst

<?php
require_once 'LegacySensorAdapter.php';

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

// TODO: Erstelle einen LegacySensor mit der Eingabetemperatur
// TODO: Wickle ihn in einen LegacySensorAdapter
// TODO: Rufe getTemperature() auf dem Adapter auf
// TODO: Gib das Ergebnis auf zwei Dezimalstellen gerundet aus
// Ausgabeformat: Temperature: [celsius]C

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