Pular para o conteúdo
GoF Padrões de Projeto Estruturais
Estrutural escopo de objeto
GoF, p. 185

Fachada

Facade

Uma porta de entrada simples para um subsistema complicado.

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

Fornecer uma interface unificada para um conjunto de interfaces de um subsistema. Facade define uma interface de nível mais alto que torna o subsistema mais fácil de usar.

Analogiauma imagem do mundo real

O atendente da central

Para pedir uma pizza você liga e fala uma frase. Do outro lado, há um sistema de pedidos, um controle de estoque, uma cozinha, um roteirizador de entrega e um gateway de pagamento. O atendente é a fachada: ele conhece todo mundo e coordena, e você só precisa saber uma coisa — o número do telefone.

O problema

Usar um subsistema exige inicializar dezenas de objetos na ordem certa, conhecer detalhes de implementação e conectar tudo. Essa “cola” acaba espalhada pela aplicação, acoplando sua lógica de negócio a um subsistema que pode mudar.

A solução

Crie uma classe com um punhado de métodos de alto nível, expressos na linguagem do seu domínio, que fazem essa coordenação por dentro. O cliente conversa só com ela.

Sintomascomo reconhecer no seu código
  • A mesma sequência de 8 chamadas repetida em vários controllers.
  • Imports de dezenas de classes internas de uma lib no seu domínio.

Estrutura

1 chamadaClientConversorDeVideo+ converter(arq, fmt)LeitorDeArquivoCodecMixerDeAudio
Fig. 10 — Facade herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
Facade
Sabe a quem delegar cada pedido e coordena o subsistema.
Additional Facade
(opcional) Segunda fachada para evitar que a primeira vire um monstro.
Subsystem classes
Fazem o trabalho real; não conhecem a fachada.
Client
Usa a fachada em vez de dezenas de classes.

Implementação

Listagem 10 Uma chamada esconde seis passos de um checkout
// ── O subsistema: classes reais, complexas, independentes ──
class Estoque      { reservar(itens)      { return { reservaId: 'r_77', itens }; } }
class Precificador { calcular(itens, cupom) { const t = itens.length * 100; return cupom ? t * 0.9 : t; } }
class Pagamentos   { cobrar(valor, cartao) { return { pago: true, tx: 'tx_42', valor }; } }
class Fiscal       { emitirNota(pedido)    { return { nfe: '35240...', pedido: pedido.id }; } }
class Logistica    { agendar(endereco)     { return { rastreio: 'BR123', prazo: '3 dias' }; } }
class Emails       { enviarConfirmacao(email, pedido) { return `✉️ enviado para ${email}`; } }

// ── A FACHADA: um método, na linguagem do negócio ─────
class CheckoutFacade {
  constructor() {
    this.estoque     = new Estoque();
    this.preco       = new Precificador();
    this.pagamentos  = new Pagamentos();
    this.fiscal      = new Fiscal();
    this.logistica   = new Logistica();
    this.emails      = new Emails();
  }

  // Toda a ordem, a coordenação e o tratamento de erro moram AQUI.
  finalizarCompra({ itens, cupom, cartao, endereco, email }) {
    const reserva = this.estoque.reservar(itens);
    const total   = this.preco.calcular(itens, cupom);
    const cobranca = this.pagamentos.cobrar(total, cartao);
    if (!cobranca.pago) throw new Error('pagamento recusado');

    const pedido  = { id: 'p_900', reserva: reserva.reservaId, total, tx: cobranca.tx };
    const nota    = this.fiscal.emitirNota(pedido);
    const entrega = this.logistica.agendar(endereco);
    this.emails.enviarConfirmacao(email, pedido);

    return { pedido: pedido.id, total, nfe: nota.nfe, rastreio: entrega.rastreio };
  }
}

// ── O cliente: 1 linha, zero conhecimento do subsistema ─
const checkout = new CheckoutFacade();
console.log(checkout.finalizarCompra({
  itens: ['sku-1', 'sku-2'], cupom: 'BEMVINDO', cartao: '4111…',
  endereco: 'Rua A, 100', email: 'ana@x.com',
}));
// { pedido: 'p_900', total: 180, nfe: '35240...', rastreio: 'BR123' }
Na práticaonde ele já existe
  • javax.faces.context.FacesContext
  • jQuery — uma fachada sobre a API do DOM
  • SDKs oficiais de serviços em nuvem (AWS SDK, Stripe SDK)

Consequências

A favor
  • Isola o código do cliente da complexidade do subsistema.
  • Reduz o acoplamento: se o subsistema mudar, só a fachada muda.
  • Dá um vocabulário de alto nível, na linguagem do domínio.
Contra
  • A fachada pode virar um objeto-deus acoplado a tudo no sistema.
  • Pode esconder capacidades legítimas do subsistema — deixe o acesso direto disponível para casos avançados.
Use quando
  • Você quer uma interface simples para um subsistema complexo.
  • Você quer organizar um subsistema em camadas — cada camada expõe sua fachada.
  • Você quer reduzir a dependência entre o cliente e muitas classes internas.
Evite quando
  • O subsistema já é simples — a fachada vira indireção vazia.

Relações com outros padrões

parecido / fácil de confundir
Adapter
Adapter adapta UM objeto a uma interface existente; Facade cria uma interface NOVA sobre VÁRIOS objetos.
Mediator
Facade define interface UNIDIRECIONAL e os subsistemas a ignoram; Mediator centraliza comunicação BIDIRECIONAL e os colegas o conhecem.
Proxy
Proxy tem a mesma interface do alvo; Facade tem uma interface própria e mais simples.
costuma andar junto
Singleton
Uma fachada sem estado geralmente pode ser única.
alternativa a
Abstract Factory
Abstract Factory pode ser uma alternativa quando o que se quer esconder é só a criação.

Verificação

Questãoa resposta está marcada

Qual é a diferença central entre Facade e Mediator?

  1. Na Facade os subsistemas não a conhecem e o fluxo é unidirecional; no Mediator os colegas o conhecem e a comunicação é bidirecional
  2. Facade só pode envolver uma classe
  3. Mediator é um padrão estrutural e Facade é comportamental
  4. Facade não pode ser usada com Singleton

Facade simplifica o acesso a um subsistema que a ignora completamente. Mediator existe para que colegas que se conhecem parem de falar entre si e falem com ele.