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 StripeDer 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.
Aufgabe
EinfachErstellen 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 einTemperatureSensor-Interface, das deine Wetteranwendung erwartet. Es sollte eine MethodegetTemperature(): floatbesitzen, die die Temperatur in Celsius zurückgibt.LegacySensor.php: Erstelle eineLegacySensor-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 eineLegacySensorAdapter-Klasse, dieTemperatureSensorimplementiert und einenLegacySensorkapselt. Dein Adapter sollte:- In seinem Konstruktor einen
LegacySensorakzeptieren getTemperature()implementieren, indem er den Fahrenheit-Wert vom älteren Sensor liest und ihn mithilfe der Formel(fahrenheit - 32) * 5 / 9in Celsius umrechnet
- In seinem Konstruktor einen
main.php: Binde die Datei LegacySensorAdapter ein. Du erhältst eine Eingabe: eine Temperatur in Fahrenheit.Erstelle mit der Eingabetemperatur einen
LegacySensorund kapsle ihn anschließend in einenLegacySensorAdapter. RufegetTemperature()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
?>Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in OOPKlassen vs. ObjekteDas Schlüsselwort $thisMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick – Einfacher Taschenrechner4Vererbung
Grundlegende VererbungDas Schlüsselwort parent::MethodenüberschreibungDas Schlüsselwort finalAbstrakte KlassenRückblick – Mitarbeiterhierarchie7Kapselung
Öffentlich, geschützt, privatZugriffsmodifikatoren im DetailGetter und SetterInformationsverbergungKonstruktor-Promotion (8.0)Wiederholung – System zur Verwaltung von Schülerdatensätzen10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objektklonen im DetailGeneratoren & Iteratoren13Entwurfsmuster Teil 2
BefehlsmusterAdaptermusterDekorierermusterSchablonenmethodenmusterZustandsmusterKompositummusterRepository-Muster2Namespaces & Autoloading
Einführung in NamespacesDas use-SchlüsselwortPSR-4-Autoloading-StandardComposer-AutoloaderRückblick – Organisiertes Projekt5Schnittstellen & Verträge
Einführung in SchnittstellenSchnittstellen implementierenMehrere Schnittstellen implementierenSchnittstelle vs. abstrakte KlasseTyp-Hinweise mit SchnittstellenRückblick – Formrechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objektklonen__serialize & __unserializeRückblick – Benutzerdefinierte Sammlung11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenBenutzerdefinierte Exception-HierarchieTry, Catch, FinallyRückblick – Formularvalidator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klassen-Eigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenSchreibgeschützte Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphie
Methodenüberschreibung erneut betrachtetPolymorphie über SchnittstellenTyp-Hinweise & Union-TypenSpätes statisches BindenRückblick – Zahlungsabwickler9Traits
Einführung in TraitsMehrere Traits verwendenAuflösung von Trait-KonfliktenAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungÜbe selbstständig: Online-PHP-Compiler