Adapter-Muster
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 76 von 91.
Das Adapter-Muster ist ein Strukturmuster, 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.
Stellen Sie sich vor, Sie entwickeln eine Anwendung, die Zahlungen verarbeitet, und Sie müssen eine Zahlungsbibliothek eines Drittanbieters integrieren. Die Bibliothek funktioniert einwandfrei, aber ihre Schnittstelle entspricht nicht dem, was Ihr Code erwartet. Anstatt Ihre gesamte Anwendung umzuschreiben, erstellen Sie einen Adapter, der zwischen den beiden vermittelt.
<?php
// Die Schnittstelle, die Ihre Anwendung erwartet
interface PaymentProcessor {
public function pay(float $amount): string;
}
// Drittanbieter-Bibliothek mit einer anderen Schnittstelle
class StripeAPI {
public function createCharge(int $cents, string $currency): string {
return "Charged {$cents} {$currency} via Stripe";
}
}
Der Adapter implementiert die von Ihnen erwartete Schnittstelle, während er intern die Klasse des Drittanbieters verwendet:
<?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 konvertiert Dollar in Cent und ruft die entsprechende Methode auf. Ihr Anwendungscode kennt nur PaymentProcessor und bleibt von den spezifischen Anforderungen von Stripe völlig unberührt. Wenn Sie später zu einem anderen Zahlungsanbieter wechseln, erstellen Sie einfach einen neuen Adapter, ohne Ihren bestehenden Code zu ändern.
Aufgabe
EinfachLassen Sie uns ein Temperaturkonvertierungssystem unter Verwendung des Adapter-Musters erstellen. Sie verfügen über einen alten Temperatursensor, der Messwerte in Fahrenheit ausgibt, aber Ihre moderne Wetteranwendung erwartet alle Temperaturen in Celsius. Anstatt eines der beiden Systeme zu modifizieren, erstellen Sie einen Adapter, der die Lücke schließt.
Sie werden Ihren Code über vier Dateien hinweg organisieren:
TemperatureSensor.php— Definieren Sie einTemperatureSensor-Interface, das Ihre Wetteranwendung erwartet. Es sollte eine MethodegetTemperature(): floathaben, die die Temperatur in Celsius zurückgibt.LegacySensor.php— Erstellen Sie eineLegacySensor-Klasse, die die alte Hardware simuliert. Diese Klasse hat ein anderes Interface als das, was Ihre Anwendung benötigt:- Sie nimmt einen Fahrenheit-Messwert in ihrem Konstruktor entgegen (verwenden Sie Constructor Promotion)
- Sie hat eine Methode
readFahrenheit(): float, die den gespeicherten Fahrenheit-Wert zurückgibt
LegacySensorAdapter.php— Binden Sie sowohl das TemperatureSensor-Interface als auch die LegacySensor-Klasse ein. Erstellen Sie eineLegacySensorAdapter-Klasse, dieTemperatureSensorimplementiert und einenLegacySensorkapselt. Ihr Adapter sollte:- Einen
LegacySensorin seinem Konstruktor akzeptieren getTemperature()implementieren, indem der Fahrenheit-Wert vom Legacy-Sensor gelesen und mit der Formel(fahrenheit - 32) * 5 / 9in Celsius umgerechnet wird
- Einen
main.php— Binden Sie die Datei LegacySensorAdapter ein. Sie erhalten eine Eingabe: eine Temperatur in Fahrenheit.Erstellen Sie einen
LegacySensormit der eingegebenen Temperatur und kapseln Sie ihn dann in einenLegacySensorAdapter. Rufen SiegetTemperature()auf dem Adapter auf und geben Sie das Ergebnis auf zwei Dezimalstellen gerundet aus.Das Ausgabeformat sollte sein:
Temperature: [celsius]C
Diese Herausforderung zeigt, wie das Adapter-Muster es Ihnen ermöglicht, inkompatible Schnittstellen zu integrieren, ohne bestehenden Code zu ändern. Ihre Wetteranwendung arbeitet ausschließlich mit dem TemperatureSensor-Interface und weiß überhaupt nicht, dass die tatsächlichen Messwerte von einem alten Fahrenheit-Sensor stammen.
Spickzettel
Das Adapter-Muster (Adapter Pattern) ist ein Strukturmuster, das es Objekten mit inkompatiblen Schnittstellen ermöglicht, zusammenzuarbeiten, indem es als Brücke zwischen ihnen fungiert.
Grundstruktur
Definieren Sie die Schnittstelle, die Ihre Anwendung erwartet:
<?php
interface PaymentProcessor {
public function pay(float $amount): string;
}Eine Drittanbieter-Klasse mit einer anderen Schnittstelle:
<?php
class StripeAPI {
public function createCharge(int $cents, string $currency): string {
return "Charged {$cents} {$currency} via Stripe";
}
}Erstellen des Adapters
Der Adapter implementiert die erwartete Schnittstelle, während er intern die Drittanbieter-Klasse verwendet:
<?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');
}
}Verwendung
$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);
// Ausgabe: Charged 2999 USD via StripeDer Adapter übersetzt zwischen Schnittstellen und ermöglicht es Ihrem Anwendungscode, unverändert zu bleiben, wenn Sie Bibliotheken von Drittanbietern integrieren oder Implementierungen wechseln.
Probier es selbst
<?php
require_once 'LegacySensorAdapter.php';
// Eingabe lesen
$fahrenheit = floatval(trim(fgets(STDIN)));
// TODO: Erstelle einen LegacySensor mit der eingegebenen Temperatur
// TODO: In einen LegacySensorAdapter einhüllen
// TODO: getTemperature() auf dem Adapter aufrufen
// TODO: Das Ergebnis auf zwei Dezimalstellen gerundet ausgeben
// 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 die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem10Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungDependency InjectionAnonyme KlassenEnums (PHP 8.1)Fibers (PHP 8.1)Objekt-Klonen im DetailGeneratoren & Iteratoren13Entwurfsmuster Teil 2
Command-MusterAdapter-MusterDecorator-MusterTemplate-Method-MusterZustandsmusterComposite-MusterRepository-Muster2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung