GoF, p. 185
Fachada
Facade
Uma porta de entrada simples para um subsistema complicado.
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.
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.
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.
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.
- 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
- 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
// ── 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' } - 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
- 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.
- 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.
- 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.
- O subsistema já é simples — a fachada vira indireção vazia.
Relações com outros padrões
- 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.
- Singleton
- Uma fachada sem estado geralmente pode ser única.
- Abstract Factory
- Abstract Factory pode ser uma alternativa quando o que se quer esconder é só a criação.
Verificação
Qual é a diferença central entre Facade e Mediator?
- Na Facade os subsistemas não a conhecem e o fluxo é unidirecional; no Mediator os colegas o conhecem e a comunicação é bidirecional
- Facade só pode envolver uma classe
- Mediator é um padrão estrutural e Facade é comportamental
- 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.