Wzorzec adaptera
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 76 z 91.
Wzorzec Adapter to strukturalny wzorzec projektowy, który umożliwia współpracę obiektów o niezgodnych interfejsach. Działa jak most między dwoma interfejsami, tłumacząc wywołania z jednego formatu na drugi.
Wyobraź sobie, że tworzysz aplikację przetwarzającą płatności i musisz zintegrować zewnętrzną bibliotekę płatniczą. Biblioteka działa doskonale, ale jej interfejs nie pasuje do tego, czego oczekuje twój kod. Zamiast przepisywać całą aplikację, tworzysz adapter, który tłumaczy komunikację między nimi.
<?php
// Interfejs, którego oczekuje Twoja aplikacja
interface PaymentProcessor {
public function pay(float $amount): string;
}
// Biblioteka innej firmy z odmiennym interfejsem
class StripeAPI {
public function createCharge(int $cents, string $currency): string {
return "Charged {$cents} {$currency} via Stripe";
}
}
Adapter implementuje oczekiwany interfejs, korzystając wewnętrznie z klasy innej firmy:
<?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);
Wynik:
Charged 2999 USD via StripeAdapter przelicza dolary na centy i wywołuje odpowiednią metodę. Twój kod aplikacji zna tylko PaymentProcessor i nie musi wiedzieć o specyficznych wymaganiach Stripe. Jeśli później zmienisz dostawcę płatności na innego, po prostu utworzysz nowy adapter bez zmieniania istniejącego kodu.
Wyzwanie
ŁatwyStwórzmy system konwersji temperatury z użyciem wzorca Adapter. Masz starszy czujnik temperatury, który podaje odczyty w stopniach Fahrenheita, ale Twoja nowoczesna aplikacja pogodowa oczekuje temperatur podanych w stopniach Celsjusza. Zamiast modyfikować którykolwiek z tych systemów, utworzysz adapter, który połączy je ze sobą.
Rozmieścisz kod w czterech plikach:
TemperatureSensor.php: Zdefiniuj interfejsTemperatureSensor, którego oczekuje aplikacja pogodowa. Powinien zawierać metodęgetTemperature(): float, która zwraca temperaturę w stopniach Celsjusza.LegacySensor.php: Utwórz klasęLegacySensor, która symuluje stary sprzęt. Ta klasa ma inny interfejs niż ten, którego potrzebuje Twoja aplikacja:- Przyjmuje odczyt w stopniach Fahrenheita w konstruktorze (użyj promocji właściwości konstruktora)
- Ma metodę
readFahrenheit(): float, która zwraca zapisaną wartość w stopniach Fahrenheita
LegacySensorAdapter.php: Dołącz zarówno interfejs TemperatureSensor, jak i klasę LegacySensor. Utwórz klasęLegacySensorAdapter, która implementuje interfejsTemperatureSensori opakowuje obiektLegacySensor. Twój adapter powinien:- Przyjmować obiekt
LegacySensorw konstruktorze - Implementować
getTemperature()przez odczytanie wartości w stopniach Fahrenheita ze starszego czujnika i przeliczenie jej na stopnie Celsjusza za pomocą wzoru:(fahrenheit - 32) * 5 / 9
- Przyjmować obiekt
main.php: Dołącz plik LegacySensorAdapter. Otrzymasz jedno wejście: temperaturę w stopniach Fahrenheita.Utwórz obiekt
LegacySensorz temperaturą wejściową, a następnie opakuj go w obiektLegacySensorAdapter. WywołajgetTemperature()adaptera i wypisz wynik zaokrąglony do dwóch miejsc po przecinku.Format wyjściowy powinien wyglądać tak:
Temperature: [celsius]C
To wyzwanie pokazuje, jak wzorzec Adapter pozwala integrować niezgodne interfejsy bez modyfikowania istniejącego kodu. Twoja aplikacja pogodowa korzysta wyłącznie z interfejsu TemperatureSensor i nie wie, że rzeczywiste odczyty pochodzą ze starszego czujnika podającego temperaturę w stopniach Fahrenheita.
Spróbuj swoich sił
<?php
require_once 'LegacySensorAdapter.php';
// Odczytaj dane wejściowe
$fahrenheit = floatval(trim(fgets(STDIN)));
// TODO: Utwórz LegacySensor z podaną temperaturą
// TODO: Umieść go w LegacySensorAdapter
// TODO: Wywołaj getTemperature() na adapterze
// TODO: Wypisz wynik zaokrąglony do dwóch miejsc po przecinku
// Format wyjściowy: Temperature: [celsius]C
?>Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów10Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieWstrzykiwanie zależnościKlasy anonimoweEnumy (PHP 8.1)Włókna (PHP 8.1)Dogłębne omówienie klonowania obiektówGeneratory i iteratory13Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytuWzorzec repozytorium2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator PHP online