Pattern strutturali: Adapter, Decorator, Facade
Componete gli oggetti e semplificate le interfacce con i pattern strutturali.
Pattern strutturali: Adapter, Decorator, Facade è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.
Comporre gli oggetti
I pattern strutturali descrivono come comporre classi e oggetti in strutture più ampie mantenendoli flessibili. Esamineremo tre strumenti fondamentali:
- Adapter — rendere utilizzabile un'interfaccia incompatibile.
- Decorator — aggiungere comportamento senza ricorrere all'ereditarietà.
- Facade — presentare un'interfaccia semplice davanti a un sottosistema complesso.
Adapter: il problema
Dipende da un'interfaccia PaymentGateway, ma un SDK di terze parti espone chargeCard($amountInCents) con una struttura diversa. Chiamare direttamente l'SDK ne diffonderebbe l'API in tutto il codice. Di seguito, le due interfacce sono chiaramente incompatibili: è esattamente questo disallineamento che un adapter risolve.
<?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 nel codice
L'adapter contiene l'adaptee e implementa l'interfaccia di destinazione, convertendo argomenti e valori restituiti. Il codice dell'applicazione rimane pulito e indipendente dal fornitore.
<?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: l'idea
Un Decorator avvolge un oggetto che condivide la sua interfaccia e aggiunge comportamento prima o dopo la delega. A differenza dell'ereditarietà, i decorator si impilano a runtime, consentendo di combinare le funzionalità in qualsiasi ordine senza una proliferazione incontrollata di classi. Ecco lo scheletro minimo: un wrapper che implementa la stessa interfaccia e contiene l'istanza interna.
<?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 nel codice
Ogni decorator implementa la stessa interfaccia e contiene un'istanza interna. Qui avvolgiamo una sorgente dati con caching e logging, componendoli liberamente.
<?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!!!
Decorator nel mondo reale
Il middleware PSR-7 / PSR-15 è essenzialmente il pattern Decorator applicato alla gestione HTTP: ogni middleware avvolge il successivo e aggiunge autenticazione, logging o caching intorno alla richiesta e alla risposta. Anche i wrapper degli stream e i livelli di cache PSR-6/16 usano comunemente la decorazione. La caratteristica fondamentale è che il wrapper è sostituibile con l'oggetto che avvolge.
Decorator o ereditarietà
L'ereditarietà fissa il comportamento a compile time e consente una sola classe base. La decorazione è dinamica e componibile. Scelga i decorator quando:
- le combinazioni di funzionalità opzionali aumentano rapidamente,
- il comportamento deve essere aggiunto o rimosso a runtime,
- è necessario estendere una classe
finalo di terze parti da cui non è possibile ereditare.
Facade: l'idea
Una Facade fornisce un unico punto di accesso semplificato a un sottosistema complesso composto da molte classi. Non nasconde il sottosistema, a cui è ancora possibile accedere direttamente, ma offre un'API comoda e di alto livello per il caso d'uso comune. Confronti la complessa sequenza di operazioni del sottosistema qui sotto con la chiamata alla facade su una sola riga nella scena successiva.
<?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 nel codice
La facade orchestra diversi collaboratori dietro un unico metodo. I client chiamano place() invece di collegare autonomamente inventario, pagamento e spedizione.
<?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;
Distinguere i tre pattern
- Adapter modifica un'interfaccia affinché due componenti esistenti possano comunicare: stesso comportamento, struttura diversa.
- Decorator mantiene l'interfaccia ma aggiunge comportamento, impilabile a runtime.
- Facade introduce una nuova interfaccia più semplice davanti a molte classi.
Un test utile: Adapter riguarda la compatibilità, Decorator il potenziamento, Facade la semplificazione.
Nota sulle facade di Laravel
Le «facade» di Laravel sono un meccanismo di proxy statico basato sul container dei servizi, non il pattern Facade di GoF. Condividono l'obiettivo di offrire un punto di accesso comodo, ma differiscono nell'implementazione. Non confonda la terminologia del framework con il pattern strutturale quando ragiona sul design.
Verifica rapida
Identifichi il pattern a partire dal suo intento.
Riepilogo
Ha composto gli oggetti con tre pattern strutturali: Adapter per collegare interfacce incompatibili, ad esempio quelle di un SDK del fornitore; Decorator per impilare il comportamento a runtime, alla base del middleware PSR-15; e Facade per offrire un'interfaccia semplice davanti a un sottosistema complesso. Ognuno riduce l'accoppiamento, così il codice resiste meglio alla dipendenza da un singolo fornitore e alla proliferazione delle funzionalità.
Domande Frequenti
La lezione «Pattern strutturali: Adapter, Decorator, Facade» è gratuita?
Sì — il testo completo di «Pattern strutturali: Adapter, Decorator, Facade» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.
Cosa imparerò in «Pattern strutturali: Adapter, Decorator, Facade»?
Componete gli oggetti e semplificate le interfacce con i pattern strutturali. Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare PHP Academy?
Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Pattern strutturali: Adapter, Decorator, Facade»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione PHP Academy?
Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- I principi SOLID nella pratica
- Pattern creazionali: Factory, Builder, Singleton
- Pattern strutturali: Adapter, Decorator, Facade
- Pattern comportamentali: Strategy, Observer, Command