0Pricing
PHP Academy · Aula

Padrões estruturais: Adapter, Decorator e Facade

Componha objetos e simplifique interfaces com padrões estruturais.

Padrões estruturais: Adapter, Decorator e Facade é uma aula grátis de PHP Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de PHP Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de PHP Academy inclui 4 aulas no total.

Compondo objetos

Os padrões estruturais descrevem como compor classes e objetos em estruturas maiores, mantendo-os flexíveis. Abordaremos três padrões essenciais:

  • Adapter — tornar utilizável uma interface incompatível.
  • Decorator — adicionar comportamento sem criar subclasses.
  • Facade — apresentar uma interface simples para um subsistema complexo.

Adapter: o problema

Você depende de uma interface PaymentGateway, mas um SDK de terceiros expõe chargeCard($amountInCents) com um formato diferente. Chamar o SDK diretamente espalha a API dele por toda parte. Abaixo, as duas interfaces são claramente incompatíveis — essa incompatibilidade é exatamente o que um adapter resolve.

<?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 no código

O adapter mantém o objeto adaptado e implementa a interface de destino, convertendo argumentos e valores de retorno. O código da sua aplicação permanece limpo e independente do fornecedor.

<?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: a ideia

Um Decorator envolve um objeto que compartilha sua interface e adiciona comportamento antes ou depois de delegar. Ao contrário da herança, os decorators podem ser empilhados em tempo de execução, permitindo combinar funcionalidades em qualquer ordem sem uma proliferação de classes. Este é o esqueleto mínimo: um encapsulador que implementa a mesma interface e mantém a instância 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 no código

Cada decorator implementa a mesma interface e mantém uma instância interna. Aqui envolvemos uma fonte de dados com armazenamento em cache e registro, compondo-os livremente.

<?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 na prática

As camadas intermediárias PSR-7/PSR-15 são essencialmente o padrão decorator aplicado ao tratamento de HTTP: cada camada envolve a próxima, adicionando autenticação, registro ou armazenamento em cache à solicitação e à resposta. Encapsuladores de fluxo e camadas de armazenamento em cache PSR-6/16 também costumam usar decoração. A característica principal é: o encapsulador pode substituir o elemento que envolve.

Decorator versus herança

A herança fixa o comportamento no momento da compilação e permite apenas uma classe base. A decoração é dinâmica e combinável. Escolha decorators quando:

  • as combinações de funcionalidades opcionais se multiplicarem,
  • o comportamento precisar ser adicionado ou removido em tempo de execução,
  • você precisar estender uma classe final ou de terceiros da qual não possa criar uma subclasse.

Facade: a ideia

Uma Facade fornece um único ponto de entrada simplificado para um subsistema complexo composto por muitas classes. Ela não oculta o subsistema (você ainda pode acessá-lo diretamente), mas oferece uma API conveniente e de alto nível para o caso comum. Compare a sequência verbosa de interações com o subsistema abaixo com a chamada de uma linha à Facade na próxima cena.

<?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 no código

A Facade coordena vários colaboradores por trás de um único método. Os clientes chamam place() em vez de configurarem o inventário, o pagamento e o envio por conta própria.

<?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;

Distinguindo os três

  • Adapter altera uma interface para que duas partes existentes possam se comunicar; o comportamento é o mesmo, mas o formato é diferente.
  • Decorator mantém a interface, mas adiciona comportamento, podendo ser empilhado em tempo de execução.
  • Facade introduz uma interface nova e mais simples diante de várias classes.

Um teste prático: Adapter trata de compatibilidade, Decorator de aprimoramento e Facade de simplificação.

Observação sobre as fachadas do Laravel

As "fachadas" do Laravel são um mecanismo de proxy estático apoiado pelo contêiner de serviços, não o padrão Facade do grupo dos Quatro. Elas compartilham o objetivo de oferecer uma interface conveniente, mas diferem na implementação. Não confunda a terminologia do framework com o padrão estrutural ao raciocinar sobre projeto.

Verificação rápida

Identifique o padrão pela sua intenção.

Recapitulação

Você compôs objetos com três padrões estruturais: Adapter para conectar interfaces incompatíveis (por exemplo, um SDK de fornecedor), Decorator para empilhar comportamentos em tempo de execução (a base das camadas intermediárias PSR-15) e Facade para oferecer uma interface simples diante de um subsistema complexo. Cada um reduz o acoplamento, tornando seu código mais resistente à dependência de fornecedores e ao excesso de funcionalidades.

Perguntas Frequentes

A aula “Padrões estruturais: Adapter, Decorator e Facade” é grátis?

Sim — o texto completo de “Padrões estruturais: Adapter, Decorator e Facade” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de PHP Academy, atualize para CoddyKit PRO. O curso de PHP Academy inclui 4 aulas no total.

O que vou aprender em “Padrões estruturais: Adapter, Decorator e Facade”?

Componha objetos e simplifique interfaces com padrões estruturais. Você pratica PHP Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar PHP Academy?

Nenhuma experiência prévia é necessária. PHP Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Padrões estruturais: Adapter, Decorator e Facade”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de PHP Academy?

Sim. Cada aula de PHP Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Princípios SOLID na prática
  2. Padrões de criação: Factory, Builder e Singleton
  3. Padrões estruturais: Adapter, Decorator e Facade
  4. Padrões comportamentais: Strategy, Observer e Command
← Voltar para PHP Academy