A torre de controle
Pilotos não negociam pista entre si por rádio; seria caos com dez aviões e impossível com cem. Todos falam com a torre, que conhece a posição de cada um e dá as ordens. Nenhum piloto precisa saber quem mais está no ar — e um avião novo entra no espaço aéreo sem que ninguém seja apresentado a ele.
O problema
Coordenação entre componentes tende a virar conhecimento mútuo. Cada regra nova adiciona uma referência, e o número de ligações cresce muito mais rápido que o número de peças.
O efeito colateral é que nenhum componente é reaproveitável: ele só compila junto com os colegas que aprendeu a chamar.
A comparação inevitável é com Observer, e a diferença é onde mora a regra. No Observer, o sujeito emite um evento e os observadores decidem sozinhos o que fazer — a lógica fica distribuída entre eles, e o sujeito não sabe nem quantos existem. No Mediator, os colegas apenas relatam, e a decisão sobre o que acontece em consequência é do mediador, num lugar só.
Isso torna os padrões complementares, não concorrentes: é muito comum implementar o canal de avisos com Observer e a lógica de reação com Mediator. O que importa é responder à pergunta 'onde vive a regra de interação?'.
Com Facade a distinção é de direção. A facade simplifica o acesso de fora para dentro, e o subsistema nem sabe que ela existe. O mediador coordena de dentro, e os colegas o conhecem explicitamente. Facade é uma porta; mediador é um centro nervoso.
O risco embutido: centralizar demais
O padrão troca muitas conexões por um ponto central — e esse ponto tende a engordar. É o único padrão do GoF cujo principal risco é o sucesso do próprio uso.
Cada regra nova de interação vai naturalmente para o mediador, porque é onde as regras moram. Depois de um ano, ele conhece quinze componentes e tem oitocentas linhas de condicionais — o god object que o padrão veio evitar, agora com um nome respeitável.
O contorno é dividir por contexto em vez de por tela: um mediador por grupo coeso de componentes, não um por aplicação. Se dois grupos não têm regras entre si, não devem compartilhar mediador.
O sinal de que passou do ponto é o mediador precisar consultar o estado de vários colegas para decidir cada coisa. Quando isso acontece, a lógica provavelmente é de domínio e deveria estar num modelo próprio, com o mediador apenas refletindo o resultado na interface.
Com Mediator: uma estrela
- cada componente conhece só o mediador
- as regras de interação ficam num lugar só
- componentes viram reaproveitáveis em outras telas
- testar uma regra é testar o mediador com colegas falsos
O custo é a centralização: o mediador concentra conhecimento e tende a engordar. Sem disciplina para dividi-lo por contexto, ele vira o gargalo de manutenção.
DialogoReserva (mediador)conhece todos e guarda as regras
Campo destinoavisa 'mudou' e nada mais
Campo dataavisa 'mudou' e nada mais
Botão reservarsó obedece ao mediador
- 1
Colega só relata
Cada componente avisa o mediador quando algo muda — sem conhecer os outros.
- 2
Mediador recebe
O centro concentra as regras: quem limpa o quê, quem habilita o botão.
- 3
Coordena os demais
A partir do aviso, o mediador atualiza os colegas necessários.
- 4
Reaproveitar
O mesmo Campo serve em outro diálogo: a regra de interação fica no mediador daquela tela.
Navegue pelas camadas
Camada 1/2Colega
use ← →Camada 1
Colega
relata, não decide
Cuida do próprio comportamento e avisa o mediador quando algo relevante acontece. Não conhece os outros componentes nem as consequências do que reporta — é isso que permite usá-lo em outro contexto.
No código
digitar(v) { this.valor = v; this.mediador.notificar('destino', 'mudou') }Se violar: colega que chama outro colega direto 'só neste caso' recriou a teia — e a exceção vira regra em poucos meses.
Estrutura
Código
interface Mediador {
notificar(origem: string, evento: string): void;
}
class Campo {
valor = "";
habilitado = true;
constructor(
private nome: string,
private mediador: Mediador,
) {}
digitar(v: string): void {
this.valor = v;
// o campo nao sabe quem se importa — so avisa
this.mediador.notificar(this.nome, "mudou");
}
}
// O mediador concentra TODAS as regras de interacao
class DialogoReserva implements Mediador {
destino = new Campo("destino", this);
data = new Campo("data", this);
botao = { habilitado: false };
notificar(origem: string, evento: string): void {
if (evento !== "mudou") return;
// regra 1: trocar o destino invalida a data escolhida
if (origem === "destino") this.data.valor = "";
// regra 2: so libera o botao com os dois preenchidos
this.botao.habilitado = Boolean(this.destino.valor && this.data.valor);
}
}
const d = new DialogoReserva();
d.destino.digitar("Lisboa");
d.data.digitar("2026-09-01");
console.log(d.botao.habilitado); // trueclass Campo:
def __init__(self, nome, mediador):
self._nome, self._mediador = nome, mediador
self.valor = ""
def digitar(self, v):
self.valor = v
# o campo nao sabe quem se importa — so avisa
self._mediador.notificar(self._nome, "mudou")
# O mediador concentra TODAS as regras de interacao
class DialogoReserva:
def __init__(self):
self.destino = Campo("destino", self)
self.data = Campo("data", self)
self.botao_habilitado = False
def notificar(self, origem, evento):
if evento != "mudou":
return
# regra 1: trocar o destino invalida a data escolhida
if origem == "destino":
self.data.valor = ""
# regra 2: so libera o botao com os dois preenchidos
self.botao_habilitado = bool(self.destino.valor and self.data.valor)
d = DialogoReserva()
d.destino.digitar("Lisboa")
d.data.digitar("2026-09-01")
print(d.botao_habilitado) # TrueCasos de uso
Formulário com campos interdependentes
Cenário
Numa reserva de viagem, escolher o destino filtra as datas disponíveis, a data altera as tarifas, e o botão de confirmar só habilita quando tudo está coerente.
Como o padrão entra
Um mediador do diálogo recebe os avisos de cada campo e aplica as regras de dependência. Os campos viram componentes genéricos, usáveis em qualquer formulário.
Trade-off: Regras de dependência complexas tornam o mediador difícil de ler, e a ordem em que ele atualiza os colegas passa a importar — atualizar o botão antes de limpar a data produz um estado momentâneo inválido.
Sala de chat
Cenário
Participantes enviam mensagens que devem chegar aos demais, com regras de silenciamento, banimento e histórico.
Como o padrão entra
A sala é o mediador: recebe a mensagem de um participante e decide para quem entregar, aplicando as regras. Nenhum participante tem referência a outro — é o exemplo canônico do padrão.
Trade-off: Como todo tráfego passa pelo centro, ele vira o gargalo de desempenho e o ponto único de falha; escalar a sala exige quebrá-la em várias ou distribuir o estado.
Coordenação entre widgets de um painel
Cenário
Num dashboard, selecionar uma região no mapa filtra o gráfico de vendas, que ajusta a tabela, que atualiza os totais.
Como o padrão entra
Um mediador do painel recebe as seleções e propaga os filtros para os widgets interessados. Cada widget continua sendo um componente independente, testável e reaproveitável.
Trade-off: Propagações em cadeia podem gerar laços (o gráfico ajusta a tabela, que reajusta o gráfico) — o mediador precisa de proteção contra reentrância, algo que raramente se prevê na primeira versão.
O mediador que os colegas ignoram
Compila, roda, passa no code review. E quebra depois.
O mediador está no diagrama, mas o campo ainda segura referência ao colega e aplica a regra 'só neste caso'. A teia volta; o centro vira burocracia.
class Campo {
valor = "";
constructor(
private nome: string,
private mediador: Mediador,
private data?: Campo, // <- ainda conhece o colega
) {}
digitar(v: string) {
this.valor = v;
this.mediador.notificar(this.nome, "mudou");
// "so neste caso" — a teia voltou pela porta dos fundos
if (this.nome === "destino" && this.data) this.data.valor = "";
}
}
// O mediador existe, mas o campo continua coordenando.
// Reaproveitar Campo noutro dialogo leva a data junto.O que quebra
- Ao reusar o campoEle carrega dependências do diálogo antigo e não compila sozinho.
- Ao mudar a regraParte vive no mediador, parte no colega — as duas saem de sincronia.
- No testeTestar um Campo exige montar os colegas que ele ainda conhece.
A saída: Colega só notifica; regra de interação só no mediador. Se a exceção 'direta' parecer inevitável, a fronteira do mediador está errada — não a regra do padrão.
Armadilhas
O mediador vira god object
É a armadilha principal e quase inevitável sem disciplina: como toda regra de interação pertence ao mediador, ele cresce sem limite natural. Quando passar de algumas centenas de linhas ou coordenar mais de meia dúzia de colegas, divida por contexto — vários mediadores pequenos são melhores que um onisciente.
Notificações em laço
O mediador reage a um aviso alterando um colega, que emite outro aviso, que faz o mediador alterar o primeiro. Sem guarda de reentrância, isso vira recursão infinita ou piscada visível na interface. Alterações feitas pelo mediador precisam ser silenciosas ou marcadas para não realimentarem o ciclo.
Confundir com Observer e perder os dois
Usar Observer esperando coordenação central espalha a regra entre os observadores; usar Mediator para simples difusão de eventos cria um centro sem propósito. A pergunta que resolve: existe regra sobre COMO os componentes reagem juntos? Se sim, Mediator. Se cada um decide sozinho, Observer.
Quando usar × quando evitar
Use quando
3- Componentes se coordenam com regras que não pertencem a nenhum deles.
- Você quer reaproveitar peças que hoje conhecem os colegas.
- As regras de interação mudam bastante e estão espalhadas.
Evite quando
3- São dois componentes e uma regra simples.
- É difusão de eventos sem regra entre receptores — use Observer.
- O conjunto é grande e sem coesão: o mediador viraria um depósito.
Testar o que ficou
3 armadilhas de Mediator viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.
Onde isto aparece de verdade
Você já usa isto, talvez sem saber o nome.
A store do ReduxComponentes não conversam entre si: todos falam com a store, que coordena as consequências.Um event busPublicadores e assinantes se desconhecem; o barramento no meio é quem sabe ligar os dois.
O padrão em uma linha
Sem nome de domínio, sem cerimônia. Só a ideia.
// Colegas falam com o mediador, não entre si.
mediador.notificar(this, "clique");O que ele cobra
1 salto a mais entre a chamada e o efeito.
- O mediador tende a concentrar lógica e crescer até virar um objeto-deus difícil de manter
- Uma indireção a mais entre colegas que antes se falavam diretamente
Não vale se: há poucos componentes e a comunicação entre eles é simples — centralizar tudo só cria um gargalo de manutenção.
Costuma ser confundido com
Onde isto aparece
Continue por aqui
- ObserverDefine uma dependência um-para-muitos: quando um objeto muda de estado, todos os seus dependentes são notificados automaticamente.
- FacadeOferece uma interface simples e de alto nível para um subsistema complexo, escondendo a coreografia entre as peças atrás de um único ponto de entrada.
- CommandTransforma uma ação em objeto, com os dados de que ela precisa. Isso permite enfileirar, agendar, registrar e desfazer operações — e desacopla quem pede de quem executa.