Menu
Coddy logo textTech

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 Stripe

Adapter 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.

challenge icon

Wyzwanie

Łatwy

Stwó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 interfejs TemperatureSensor, 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 interfejs TemperatureSensor i opakowuje obiekt LegacySensor. Twój adapter powinien:
    • Przyjmować obiekt LegacySensor w 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
  • main.php: Dołącz plik LegacySensorAdapter. Otrzymasz jedno wejście: temperaturę w stopniach Fahrenheita.

    Utwórz obiekt LegacySensor z temperaturą wejściową, a następnie opakuj go w obiekt LegacySensorAdapter. Wywołaj getTemperature() 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

?>
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online