Menu
Coddy logo textTech

Padrão Adapter

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 76 de 91.

O Padrão Adapter é um padrão de projeto estrutural que permite que objetos com interfaces incompatíveis trabalhem juntos. Ele atua como uma ponte entre duas interfaces, traduzindo chamadas de um formato para outro.

Imagine que você está construindo uma aplicação que processa pagamentos e precisa integrar uma biblioteca de pagamentos de terceiros. A biblioteca funciona perfeitamente, mas sua interface não corresponde ao que seu código espera. Em vez de reescrever toda a sua aplicação, você cria um adaptador que faz a tradução entre as duas.

<?php
// A interface que sua aplicação espera
interface PaymentProcessor {
    public function pay(float $amount): string;
}

// Biblioteca de terceiros com uma interface diferente
class StripeAPI {
    public function createCharge(int $cents, string $currency): string {
        return "Charged {$cents} {$currency} via Stripe";
    }
}

O adaptador implementa a interface esperada enquanto utiliza internamente a classe de terceiros:

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

Saída:

Charged 2999 USD via Stripe

O adaptador converte dólares em centavos e chama o método apropriado. O código da sua aplicação conhece apenas o PaymentProcessor, permanecendo alegremente alheio aos requisitos específicos do Stripe. Se você mudar posteriormente para um provedor de pagamento diferente, basta criar um novo adaptador sem alterar o código existente.

challenge icon

Desafio

Fácil

Vamos construir um sistema de conversão de temperatura usando o Adapter Pattern. Você tem um sensor de temperatura legado que fornece leituras em Fahrenheit, mas sua aplicação meteorológica moderna espera todas as temperaturas em Celsius. Em vez de modificar qualquer um dos sistemas, você criará um adaptador que preenche essa lacuna.

Você organizará seu código em quatro arquivos:

  • TemperatureSensor.php — Defina uma interface TemperatureSensor que sua aplicação meteorológica espera. Ela deve ter um método getTemperature(): float que retorna a temperatura em Celsius.
  • LegacySensor.php — Crie uma classe LegacySensor que simula o hardware antigo. Esta classe possui uma interface diferente da que sua aplicação precisa:
    • Ela recebe uma leitura em Fahrenheit em seu construtor (use promoção de construtor)
    • Ela possui um método readFahrenheit(): float que retorna o valor em Fahrenheit armazenado
  • LegacySensorAdapter.php — Inclua tanto a interface TemperatureSensor quanto a classe LegacySensor. Crie uma classe LegacySensorAdapter que implementa TemperatureSensor e envolve um LegacySensor. Seu adaptador deve:
    • Aceitar um LegacySensor em seu construtor
    • Implementar getTemperature() lendo o valor em Fahrenheit do sensor legado e convertendo-o para Celsius usando a fórmula: (fahrenheit - 32) * 5 / 9
  • main.php — Inclua o arquivo LegacySensorAdapter. Você receberá uma entrada: uma temperatura em Fahrenheit.

    Crie um LegacySensor com a temperatura de entrada e, em seguida, envolva-o em um LegacySensorAdapter. Chame getTemperature() no adaptador e imprima o resultado arredondado para duas casas decimais.

    O formato de saída deve ser: Temperature: [celsius]C

Este desafio demonstra como o Adapter Pattern permite integrar interfaces incompatíveis sem modificar o código existente. Sua aplicação meteorológica trabalha exclusivamente com a interface TemperatureSensor, completamente alheia ao fato de que as leituras reais vêm de um sensor Fahrenheit legado.

Folha de consulta

O Adapter Pattern (Padrão Adaptador) é um padrão de projeto estrutural que permite que objetos com interfaces incompatíveis trabalhem juntos, agindo como uma ponte entre eles.

Estrutura Básica

Defina a interface que sua aplicação espera:

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

Uma classe de terceiros com uma interface diferente:

<?php
class StripeAPI {
    public function createCharge(int $cents, string $currency): string {
        return "Charged {$cents} {$currency} via Stripe";
    }
}

Criando o Adaptador

O adaptador implementa a interface esperada enquanto utiliza internamente a classe de terceiros:

<?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');
    }
}

Uso

$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);
// Saída: Charged 2999 USD via Stripe

O adaptador traduz entre interfaces, permitindo que o código da sua aplicação permaneça inalterado ao integrar bibliotecas de terceiros ou trocar implementações.

Experimente você mesmo

<?php
require_once 'LegacySensorAdapter.php';

// Ler entrada
$fahrenheit = floatval(trim(fgets(STDIN)));

// TODO: Criar um LegacySensor com a temperatura de entrada
// TODO: Envolvê-lo em um LegacySensorAdapter
// TODO: Chamar getTemperature() no adaptador
// TODO: Imprimir o resultado arredondado para duas casas decimais
// Formato de saída: Temperature: [celsius]C

?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos