PHP Academy · Lektion

Strukturella mönster: Adapter, Decorator, Facade

Sätt samman objekt och förenkla gränssnitt med strukturella designmönster.

Lektion 3 av 413 steg

Strukturella mönster: Adapter, Decorator, Facade är en gratis lektion i PHP Academy på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för PHP Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i PHP Academy innehåller totalt 4 lektioner.

Sätta samman objekt

Strukturella mönster beskriver hur man sätter samman klasser och objekt till större strukturer och samtidigt behåller flexibiliteten. Vi går igenom tre arbetshästar:

  • Adapter — gör ett inkompatibelt gränssnitt användbart.
  • Decorator — lägger till beteende utan arv.
  • Facade — presenterar en enkel framsida till ett komplext delsystem.

Adapter: problemet

Du är beroende av gränssnittet PaymentGateway, men ett SDK från en tredjepart exponerar chargeCard($amountInCents) med en annan utformning. Om du anropar SDK:t direkt läcker dess API ut överallt. Nedan är de två gränssnitten tydligt inkompatibla — just den skillnaden är vad en adapter löser.

<?php
// What our app wants to depend on
interface PaymentGateway { public function pay(float $dollars): string; }

// What the vendor actually gives us (cents, array result)
final class StripeSdk {
    public function chargeCard(int $cents): array {
        return ['id' => 'ch_1', 'amount' => $cents];
    }
}
// dollars vs cents, string vs array -> shapes don't line up
var_dump((new StripeSdk())->chargeCard(2000));

Adapter i kod

Adaptern innehåller adaptee-objektet och implementerar ditt målgränssnitt genom att konvertera argument och returvärden. Applikationskoden förblir ren och oberoende av leverantören.

<?php
interface PaymentGateway { public function pay(float $dollars): string; }

// Third-party SDK with an incompatible API
final class StripeSdk {
    public function chargeCard(int $cents): array {
        return ['id' => 'ch_1', 'amount' => $cents];
    }
}

final class StripeAdapter implements PaymentGateway {
    public function __construct(private StripeSdk $sdk) {}
    public function pay(float $dollars): string {
        $res = $this->sdk->chargeCard((int) round($dollars * 100));
        return "charged {$res['amount']}c -> {$res['id']}";
    }
}
echo (new StripeAdapter(new StripeSdk()))->pay(20.0), PHP_EOL;

Decorator: idén

En Decorator omsluter ett objekt som delar dess gränssnitt och lägger till beteende före eller efter delegeringen. Till skillnad från arv kan decorators staplas vid körning, så att du kan kombinera funktioner i valfri ordning utan en lavin av klasser. Här är det minimala skelettet: ett omslag som implementerar samma gränssnitt och innehåller den inre instansen.

<?php
interface Coffee { public function cost(): float; }
final class Espresso implements Coffee {
    public function cost(): float { return 2.0; }
}
final class WithMilk implements Coffee {
    public function __construct(private Coffee $inner) {}
    public function cost(): float { return $this->inner->cost() + 0.5; }
}
echo (new WithMilk(new Espresso()))->cost(), PHP_EOL; // 2.5

Decorator i kod

Varje decorator implementerar samma gränssnitt och innehåller en inre instans. Här omsluter vi en datakälla med cachning och loggning och kombinerar dem fritt.

<?php
interface DataSource { public function read(): string; }

final class FileSource implements DataSource {
    public function read(): string { return 'raw-data'; }
}

final class UpperCaseDecorator implements DataSource {
    public function __construct(private DataSource $inner) {}
    public function read(): string { return strtoupper($this->inner->read()); }
}
final class ExclaimDecorator implements DataSource {
    public function __construct(private DataSource $inner) {}
    public function read(): string { return $this->inner->read() . '!!!'; }
}

$src = new ExclaimDecorator(new UpperCaseDecorator(new FileSource()));
echo $src->read(), PHP_EOL; // RAW-DATA!!!

Decorators i praktiken

Middleware i PSR-7 / PSR-15 är i princip decoratormönstret tillämpat på HTTP-hantering: varje middleware omsluter nästa och lägger till autentisering, loggning eller cachning runt begäran och svaret. Strömmomslag och cache-lager för PSR-6/16 använder också ofta decoration. Den centrala egenskapen är att omslaget kan ersätta det som det omsluter.

Decorator jämfört med arv

Arv låser fast beteendet vid kompilering och tillåter bara en basklass. Decoration är dynamisk och komponerbar. Välj decorators när:

  • kombinationerna av valfria funktioner blir många,
  • beteende ska kunna läggas till eller tas bort vid körning,
  • du måste utöka en final-klass eller en tredjepartsklass som du inte kan ärva från.

Facade: idén

En Facade tillhandahåller en enda, förenklad ingång till ett komplext delsystem med många klasser. Den döljer inte delsystemet (du kan fortfarande komma åt det direkt), men erbjuder ett praktiskt API på hög nivå för det vanliga fallet. Jämför den omständliga hanteringen av delsystemet nedan med det ensidiga facade-anropet i nästa scen.

<?php
// Without a facade, the client wires every step itself
final class Cpu { public function boot(): string { return 'cpu '; } }
final class Disk { public function load(): string { return 'disk '; } }
final class Ram { public function check(): string { return 'ram'; } }

$out = (new Cpu())->boot() . (new Disk())->load() . (new Ram())->check();
echo $out, PHP_EOL; // cpu disk ram

Facade i kod

Facaden samordnar flera samarbetande objekt bakom en metod. Klienter anropar place() i stället för att själva koppla ihop lagerhantering, betalning och leverans.

<?php
final class Inventory { public function reserve(string $sku): bool { return true; } }
final class Payments { public function charge(float $amt): bool { return true; } }
final class Shipping { public function dispatch(string $sku): string { return 'tracking-99'; } }

final class OrderFacade {
    public function __construct(
        private Inventory $inv,
        private Payments $pay,
        private Shipping $ship
    ) {}
    public function place(string $sku, float $amount): string {
        if (!$this->inv->reserve($sku)) { return 'out of stock'; }
        if (!$this->pay->charge($amount)) { return 'payment failed'; }
        return 'shipped: ' . $this->ship->dispatch($sku);
    }
}
echo (new OrderFacade(new Inventory(), new Payments(), new Shipping()))
    ->place('ABC', 49.99), PHP_EOL;

Skilj de tre åt

  • Adapter ändrar ett gränssnitt så att två befintliga delar kan kommunicera; samma beteende, annan form.
  • Decorator behåller gränssnittet men lägger till beteende och kan staplas vid körning.
  • Facade introducerar ett nytt, enklare gränssnitt framför många klasser.

Ett användbart test är: Adapter handlar om kompatibilitet, Decorator om utökning och Facade om förenkling.

Anmärkning om Laravel-fasader

Laravels ”facades” är en mekanism med statisk proxy som bygger på service containern, inte GoF:s Facade-mönster. De delar målet att erbjuda en praktisk framsida, men skiljer sig åt i implementation. Blanda inte ihop ramverkets terminologi med det strukturella mönstret när du resonerar om design.

Snabb kontroll

Identifiera mönstret utifrån dess syfte.

Sammanfattning

Du satte samman objekt med tre strukturella mönster: Adapter för att överbrygga inkompatibla gränssnitt (t.ex. ett SDK från en leverantör), Decorator för att stapla beteende vid körning (grunden för PSR-15-middleware) och Facade för att skapa en enkel framsida till ett komplext delsystem. Alla minskar kopplingen, så att koden står emot leverantörsberoende och svällande funktionalitet.

Gratis att börja

Lär dig PHP med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
49
Lektioner
195

Vanliga frågor

Är lektionen ”Strukturella mönster: Adapter, Decorator, Facade” gratis?

Ja – hela texten till ”Strukturella mönster: Adapter, Decorator, Facade” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i PHP Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i PHP Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Strukturella mönster: Adapter, Decorator, Facade”?

Sätt samman objekt och förenkla gränssnitt med strukturella designmönster. Ni övar på PHP Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig PHP Academy?

Du behöver inga förkunskaper. Utbildningen i PHP Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Strukturella mönster: Adapter, Decorator, Facade”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här PHP Academy-lektionen?

Ja. Varje PHP Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. SOLID-principerna i praktiken
  2. Skapande mönster: Factory, Builder, Singleton
  3. Strukturella mönster: Adapter, Decorator, Facade
  4. Beteendemönster: Strategy, Observer, Command
← Tillbaka till PHP Academy