DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on • Edited on

Padrão Mediator

Introdução

O Mediator é um padrão de design comportamental (do catálogo GoF). Seu objetivo é reduzir o acoplamento direto entre objetos, centralizando a comunicação em um objeto intermediário chamado mediador.

Em sistemas grandes vários objetos interagem entre si. Se cada objeto se comunicar diretamente com os outros, o sistema fica aclopado como uma “teia” de dependências difícil de manter. O Mediador entra nesse cenário, e atua como um “hub”, onde em vez de os objetos conversarem entre si diretamente, eles falam com o mediador, que decide para onde a mensagem vai.

Analogia

Imagine um aeroporto:

  • Os pilotos não ficam falando uns com os outros diretamente pelo rádio
  • Eles falam com a torre de controle (o mediador)
  • A torre organiza e coordena a comunicação, evitando conflitos

Estrutura do Mediator

  • Mediator (interface/abstração): define como os colegas (colleagues) se comunicam atráves dele
  • ConcreteMediator: Implementa a lógica de coordenação
  • Colleagues: objetos que dependem do mediador para interagir

Exemplo prático

A seguir tratrei dois exemplos práticos. O primeiro considera o método tradicional de comunicação entre a comunicação de objetos, e o segundo com o padrão Mediator implementado.

Sem Mediator

No exemplo abaixo, dois módulos (chat de usuários) se comunicam diretamente entre si:

public class Usuario
{
    public string Nome { get; }

    public Usuario(string nome)
    {
        Nome = nome;
    }

    public void EnviarMensagem(string msg, Usuario destinatario)
    {
        destinatario.ReceberMensagem($"{Nome}: {msg}");
    }

    public void ReceberMensagem(string msg)
    {
        Console.WriteLine(msg);
    }
}

// Uso:
var ana = new Usuario("Ana");
var bruno = new Usuario("Bruno");

ana.EnviarMensagem("Olá, Bruno!", bruno);
bruno.EnviarMensagem("Oi, Ana!", ana);
Enter fullscreen mode Exit fullscreen mode
  • Cada usuário precisa conhecer os outros.
  • Se quisermos adicionar regras de negócio (como logs, bloqueios, histórico, filtros, etc.), teremos que alterar o código de todos os objetos que enviam mensagens.
  • O sistema rapidamente se torna difícil de manter.

Com Mediator

Agora introduzimos um ChatMediator para intermediar as mensagens:

// Interface do Mediator
public interface IChatMediator
{
    void EnviarMensagem(string mensagem, Usuario usuario);
    void AdicionarUsuario(Usuario usuario);
}

// Implementação concreta do Mediator
public class ChatMediator : IChatMediator
{
    private readonly List<Usuario> _usuarios = new();

    public void AdicionarUsuario(Usuario usuario) => _usuarios.Add(usuario);

    public void EnviarMensagem(string mensagem, Usuario usuario)
    {
        foreach (var u in _usuarios)
        {
            if (u != usuario)
                u.ReceberMensagem(mensagem);
        }
    }
}

// Colleague
public class Usuario
{
    private readonly IChatMediator _mediator;
    public string Nome { get; }

    public Usuario(string nome, IChatMediator mediator)
    {
        Nome = nome;
        _mediator = mediator;
        _mediator.AdicionarUsuario(this);
    }

    public void EnviarMensagem(string msg)
    {
        _mediator.EnviarMensagem($"{Nome}: {msg}", this);
    }

    public void ReceberMensagem(string msg)
    {
        Console.WriteLine(msg);
    }
}

// Uso:
var chat = new ChatMediator();
var ana = new Usuario("Ana", chat);
var bruno = new Usuario("Bruno", chat);

ana.EnviarMensagem("Olá, Bruno!");
bruno.EnviarMensagem("Oi, Ana!");
Enter fullscreen mode Exit fullscreen mode
  • Os usuários não conhecem uns aos outros, apenas o mediador.
  • Regras como logs, histórico, notificações ou moderação podem ser implementadas no mediador, sem alterar as classes de usuário.
  • O sistema fica mais coeso e desacoplado

No .NET moderno, esse padrão é muito utilizado através da biblioteca MediatR, que implementa o conceito para lidar com commands e queries em arquitetura como **CQRS** e Clean Architecture.

Top comments (0)