Pular para o conteúdo
GoF Padrões de Projeto Estruturais
Estrutural escopo de classe/objeto
GoF, p. 139 também chamado de Wrapper

Adaptador

Adapter

Traduz a interface de uma classe para outra que o cliente já espera.

Complexidade simples Frequência de uso muito comum
Intençãocomo o livro define

Converter a interface de uma classe em outra interface que os clientes esperam. Adapter permite que classes trabalhem juntas quando isso seria impossível por incompatibilidade de interfaces.

Analogiauma imagem do mundo real

O adaptador de tomada

Seu notebook tem plugue americano; a tomada do hotel é europeia. Ninguém reprojeta o notebook nem a parede: você compra um adaptador. Ele não gera energia nem muda a voltagem — apenas traduz um formato de conexão para outro.

O problema

Você tem uma classe útil (uma biblioteca de terceiros, um sistema legado) cuja interface não bate com a que seu código usa. Você não pode alterá-la — é de terceiros, ou é usada por outros mil lugares.

A solução

Crie uma classe intermediária que implementa a interface esperada pelo cliente e, por dentro, delega para o objeto incompatível, convertendo dados e chamadas nos dois sentidos.

Sintomascomo reconhecer no seu código
  • Conversões de formato repetidas em vários pontos do código.
  • Detalhes de uma lib de terceiros vazando para dentro do domínio.

Estrutura

usadelega e traduzClient«interface»ServicoDados+ buscar(): JSONAdaptadorXML+ buscar(): JSONServicoXMLLegado+ fetchXML(): XML
Fig. 6 — Adapter herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
Target
A interface que o cliente já usa e entende.
Adaptee
A classe existente e incompatível que se quer aproveitar.
Adapter
Implementa Target e traduz cada chamada para o Adaptee.
Client
Programa contra Target; não sabe que existe um Adaptee.

Implementação

Listagem 6 Encaixando uma API de terceiros na interface da sua aplicação
// ── Target: a interface que TODO o seu app já usa ─────
class ProvedorDePagamento {
  async cobrar(valorEmCentavos, cartao) { throw new Error('abstrato'); }
}

// ── Adaptee: a lib do gateway, com outra assinatura ───
class GatewayLegado {
  // Trabalha com reais em string, campos com outros nomes e callback.
  executeTransaction(payload, callback) {
    const ok = payload.card_number?.length === 16;
    callback(ok ? null : new Error('CARD_INVALID'), { transaction_id: 'tx_918', status: ok ? 'OK' : 'FAIL' });
  }
}

// ── Adapter: implementa Target, fala com o Adaptee ────
class AdaptadorGatewayLegado extends ProvedorDePagamento {
  constructor(legado = new GatewayLegado()) { super(); this.legado = legado; }

  cobrar(valorEmCentavos, cartao) {
    // 1. traduz os DADOS de entrada
    const payload = {
      amount_brl: (valorEmCentavos / 100).toFixed(2),
      card_number: cartao.numero,
      exp: `${cartao.mes}/${cartao.ano}`,
    };
    // 2. traduz o PROTOCOLO (callback → Promise)
    return new Promise((resolve, reject) => {
      this.legado.executeTransaction(payload, (erro, resposta) => {
        if (erro) return reject(new Error(`Pagamento recusado: ${erro.message}`));
        // 3. traduz os DADOS de saída
        resolve({ id: resposta.transaction_id, aprovado: resposta.status === 'OK' });
      });
    });
  }
}

// O cliente não faz ideia de que existe um sistema legado ali dentro.
async function checkout(provedor) {
  const r = await provedor.cobrar(19900, { numero: '4111111111111111', mes: '12', ano: '30' });
  console.log(r.aprovado ? `✅ pago (${r.id})` : '❌ recusado');
}
checkout(new AdaptadorGatewayLegado());
Na práticaonde ele já existe
  • java.io.InputStreamReader (InputStream → Reader)
  • java.util.Arrays.asList()
  • Ponte entre APIs REST e GraphQL num BFF

Consequências

A favor
  • Separa a conversão de interface da lógica de negócio (Responsabilidade Única).
  • Permite introduzir novos adaptadores sem tocar no cliente (Aberto/Fechado).
  • Viabiliza reutilizar código que, de outra forma, seria incompatível.
Contra
  • Aumenta a complexidade: mais uma camada de indireção.
  • Às vezes é mais simples ajustar a própria classe de serviço — quando ela é sua.
Use quando
  • Você quer usar uma classe existente cuja interface não bate com a sua.
  • Você precisa reutilizar várias subclasses que não têm uma funcionalidade comum e não pode alterá-las.
  • Você está isolando seu domínio de bibliotecas externas (a camada anticorrupção do DDD).
Evite quando
  • Você controla as duas pontas e pode simplesmente alinhar as interfaces.

Relações com outros padrões

parecido / fácil de confundir
Bridge
Bridge é projetada ANTES, para deixar as partes evoluírem; Adapter é aplicada DEPOIS, para consertar incompatibilidade.
Decorator
Decorator mantém a interface e adiciona comportamento; Adapter muda a interface.
Proxy
Proxy mantém a MESMA interface e controla o acesso; Adapter converte.
Facade
Facade cria uma interface NOVA e simplificada para um subsistema; Adapter reusa uma interface existente.

Verificação

Questãoa resposta está marcada

Adapter, Decorator e Proxy envolvem outro objeto. O que distingue o Adapter?

  1. O Adapter MUDA a interface; Decorator e Proxy preservam a interface original
  2. O Adapter é o único que usa herança
  3. O Adapter é o único que pode ser aplicado em tempo de execução
  4. O Adapter é o único que pode envolver mais de um objeto

Decorator preserva a interface e acrescenta comportamento; Proxy preserva a interface e controla o acesso; Adapter existe justamente para trocar a interface.