Pular para o conteúdo
GoF Padrões de Projeto Comportamentais
Comportamental escopo de objeto
GoF, p. 273 também chamado de Intermediary, Controller

Mediador

Mediator

Objetos param de falar entre si e passam a falar com um intermediário.

Complexidade média Frequência de uso moderada
Intençãocomo o livro define

Definir um objeto que encapsula como um conjunto de objetos interage. Mediator promove o acoplamento fraco ao evitar que os objetos se refiram uns aos outros explicitamente, e permite variar a interação independentemente.

Analogiauma imagem do mundo real

A torre de controle

Os pilotos não negociam a pista entre si por rádio — seria o caos e cada avião teria que conhecer todos os outros. Todos falam com a torre, e a torre decide quem pousa quando. A torre não pilota nenhum avião; ela só coordena.

O problema

Componentes que se conhecem diretamente formam uma malha: N objetos podem gerar N² ligações. Um campo de formulário que habilita outro, que limpa um terceiro, que revalida o primeiro — nada disso é reutilizável, porque cada componente carrega referências aos outros.

A solução

Corte a comunicação direta. Cada componente conhece apenas o mediador e o notifica quando algo acontece. O mediador contém toda a lógica de coordenação e decide quem deve reagir.

Sintomascomo reconhecer no seu código
  • Uma classe de UI que importa todas as outras classes de UI.
  • Efeito dominó: mexer num componente quebra três outros.

Estrutura

notificanotificanotifica«interface»Mediador+ notificar(origem, ev)DialogoDeCadastroCampoTextoCheckboxBotao
Fig. 17 — Mediator herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
Mediator
Interface de comunicação com os componentes (geralmente um único `notificar`).
ConcreteMediator
Conhece todos os componentes e implementa a coordenação.
Component
Conhece apenas o mediador; nunca outros componentes.

Implementação

Listagem 17 Formulário onde os campos não se conhecem
// ── Componente base: conhece SÓ o mediador ────────────
class Componente {
  constructor(nome) { this.nome = nome; this.mediador = null; this.habilitado = true; }
  mudou(evento, dados) { this.mediador?.notificar(this, evento, dados); }
}

class Campo extends Componente {
  valor = '';
  digitar(v) { this.valor = v; this.mudou('digitou'); }
}
class Caixa extends Componente {
  marcada = false;
  alternar() { this.marcada = !this.marcada; this.mudou('alternou'); }
}
class Botao extends Componente {
  clicar() { if (this.habilitado) this.mudou('clicou'); }
}

// ── Mediador: TODA a lógica de coordenação num lugar só ──
class FormularioCadastro {
  constructor() {
    this.email  = new Campo('email');
    this.cupom  = new Campo('cupom');
    this.temCupom = new Caixa('temCupom');
    this.enviar = new Botao('enviar');
    for (const c of [this.email, this.cupom, this.temCupom, this.enviar]) c.mediador = this;
    this.cupom.habilitado = false;
    this.enviar.habilitado = false;
  }

  notificar(origem, evento) {
    // As regras de interação ficam explícitas e legíveis, em UM lugar.
    if (origem === this.temCupom && evento === 'alternou') {
      this.cupom.habilitado = this.temCupom.marcada;
      if (!this.temCupom.marcada) this.cupom.valor = '';
    }
    if (evento === 'digitou' || evento === 'alternou') {
      const emailOk = /\S+@\S+\.\S+/.test(this.email.valor);
      const cupomOk = !this.temCupom.marcada || this.cupom.valor.length >= 4;
      this.enviar.habilitado = emailOk && cupomOk;
    }
    if (origem === this.enviar && evento === 'clicou') {
      console.log('📨 enviando:', { email: this.email.valor, cupom: this.cupom.valor || null });
    }
  }
}

const form = new FormularioCadastro();
form.email.digitar('ana@x.com');
form.temCupom.alternar();
form.cupom.digitar('BEMVINDO');
form.enviar.clicar();          // 📨 enviando: { email: 'ana@x.com', cupom: 'BEMVINDO' }
Na práticaonde ele já existe
  • java.util.Timer — coordena tarefas agendadas
  • java.util.concurrent.ExecutorService
  • Controllers do padrão MVC; message brokers e event buses

Consequências

A favor
  • Reduz o acoplamento entre componentes — eles viram reutilizáveis.
  • A lógica de interação fica num lugar só, fácil de ler e alterar.
  • Novos mediadores mudam o comportamento do conjunto sem tocar nos componentes.
Contra
  • O mediador pode crescer até virar um objeto-deus — o problema só mudou de lugar.
Use quando
  • Mudar uma classe exige mudar várias outras por causa de dependências cruzadas.
  • Componentes não podem ser reutilizados porque dependem de muitos outros.
  • Você cria subclasses só para variar como os objetos colaboram.
Evite quando
  • Há poucos componentes com interações simples e diretas.

Relações com outros padrões

costuma andar junto
Observer
Mediator costuma ser IMPLEMENTADO com Observer; a diferença é a intenção — Mediator elimina dependências mútuas, Observer estabelece assinatura dinâmica unidirecional.
Command
A comunicação com o mediador pode ser feita via comandos.
parecido / fácil de confundir
Facade
Facade simplifica acesso a um subsistema que a ignora; Mediator é conhecido pelos colegas e centraliza a comunicação entre eles.
alternativa a
Chain of Responsibility
Outra forma de desacoplar remetente e receptor, mas em cadeia.

Verificação

Questãoa resposta está marcada

Qual é o risco mais comum ao aplicar Mediator?

  1. O mediador acumular tanta lógica que vira um objeto-deus
  2. Os componentes ficarem acoplados entre si
  3. Perder a possibilidade de testar os componentes isoladamente
  4. A comunicação virar necessariamente assíncrona

Você troca uma malha de dependências por um hub. Se o hub concentrar toda a lógica de toda a tela, ele mesmo se torna o problema — divida em mediadores menores.