Skip to content
SP StackPractices
intermediate

Patrón Mediator

Define un objeto que encapsula cómo interactúa un conjunto de objetos. Un patrón de comportamiento para reducir dependencias caóticas.

Temas: design

Patrón Mediator

Visión General

El Patrón Mediator es un patrón de diseño de comportamiento que define un objeto que encapsula cómo interactúa un conjunto de objetos. En lugar de que los objetos se refieran entre sí directamente, se comunican a través de un mediador central. Esto reduce el número de conexiones directas entre componentes y centraliza la lógica de coordinación compleja.

Cuándo Usarlo

Usa el Patrón Mediator cuando:

  • Tienes muchos objetos que necesitan comunicarse de formas complejas
  • Las dependencias entre objetos crean un lío enredado (código spaghetti)
  • Quieres centralizar la lógica de coordinación compleja
  • Reusar un componente individual es difícil porque depende de muchos otros
  • Un cambio en un componente fuerza cambios en muchos otros

Solución

Python

from abc import ABC, abstractmethod

class ChatMediator(ABC):
    @abstractmethod
    def send_message(self, message: str, sender):
        pass

    @abstractmethod
    def add_user(self, user):
        pass

class ChatRoom(ChatMediator):
    def __init__(self):
        self.users = []

    def add_user(self, user):
        self.users.append(user)

    def send_message(self, message: str, sender):
        for user in self.users:
            if user != sender:
                user.receive(message, sender.name)

class User:
    def __init__(self, name: str, mediator: ChatMediator):
        self.name = name
        self.mediator = mediator
        mediator.add_user(self)

    def send(self, message: str):
        print(f"{self.name} envía: {message}")
        self.mediator.send_message(message, self)

    def receive(self, message: str, from_name: str):
        print(f"{self.name} recibe de {from_name}: {message}")

# Uso
room = ChatRoom()
alice = User("Alice", room)
bob = User("Bob", room)

alice.send("¡Hola a todos!")

JavaScript

class ChatRoom {
  constructor() {
    this.users = [];
  }

  addUser(user) {
    this.users.push(user);
  }

  sendMessage(message, sender) {
    for (const user of this.users) {
      if (user !== sender) {
        user.receive(message, sender.name);
      }
    }
  }
}

class User {
  constructor(name, mediator) {
    this.name = name;
    this.mediator = mediator;
    mediator.addUser(this);
  }

  send(message) {
    console.log(`${this.name} envía: ${message}`);
    this.mediator.sendMessage(message, this);
  }

  receive(message, fromName) {
    console.log(`${this.name} recibe de ${fromName}: ${message}`);
  }
}

// Uso
const room = new ChatRoom();
const alice = new User("Alice", room);
const bob = new User("Bob", room);

alice.send("¡Hola a todos!");

Java

import java.util.ArrayList;
import java.util.List;

public interface ChatMediator {
    void sendMessage(String message, User sender);
    void addUser(User user);
}

public class ChatRoom implements ChatMediator {
    private final List<User> users = new ArrayList<>();

    public void addUser(User user) {
        users.add(user);
    }

    public void sendMessage(String message, User sender) {
        for (User user : users) {
            if (user != sender) {
                user.receive(message, sender.getName());
            }
        }
    }
}

public class User {
    private final String name;
    private final ChatMediator mediator;

    public User(String name, ChatMediator mediator) {
        this.name = name;
        this.mediator = mediator;
        mediator.addUser(this);
    }

    public String getName() { return name; }

    public void send(String message) {
        System.out.println(name + " envía: " + message);
        mediator.sendMessage(message, this);
    }

    public void receive(String message, String fromName) {
        System.out.println(name + " recibe de " + fromName + ": " + message);
    }
}

// Uso
ChatRoom room = new ChatRoom();
User alice = new User("Alice", room);
User bob = new User("Bob", room);
alice.send("¡Hola a todos!");

Explicación

El Patrón Mediator tiene dos roles:

  • Mediator (ChatRoom): Define la interfaz para la comunicación entre componentes
  • Colegas (User): Objetos que se comunican a través del mediador en lugar de directamente

Sin el mediador, cada usuario necesitaría una referencia a cada otro usuario. Con él, cada usuario solo necesita una referencia al mediador.

Variantes

VarianteDescripciónCaso de Uso
Event BusPub/sub desacoplado vía un canal centralSistemas grandes con muchos publishers/subscribers
Command BusComandos enrutados a través de un handler centralCQRS, despacho de tareas
Dialog DirectorWidgets UI coordinados por un controlador de diálogoValidación de formularios, flujos de wizard

Buenas Prácticas

  • Mantén el mediador enfocado en coordinación, no en lógica de negocio
  • Evita convertir el mediador en un objeto dios — si crece demasiado, divídelo
  • Documenta qué eventos maneja el mediador para que los colegas sepan qué esperar
  • Considera un event bus para sistemas muy grandes donde un solo mediador sería un cuello de botella
  • Haz el mediador observable para que sistemas externos puedan monitorear interacciones

Errores Comunes

  • Poner demasiada lógica en el mediador, creando una “god class” difícil de mantener
  • Usar un mediador cuando simples llamadas directas serían suficientes (sobre-ingeniería)
  • Hacer del mediador un cuello de botella centralizando toda la comunicación de forma bloqueante
  • No documentar el rol del mediador, haciendo difícil entender por qué los componentes no se comunican directamente
  • Permitir que el mediador filtre detalles de colegas a otros colegas

Preguntas Frecuentes

P: ¿Es Mediator lo mismo que Observer? R: Relacionados pero diferentes. Observer es una dependencia uno-a-muchos donde los sujetos notifican a los observadores. Mediator centraliza la comunicación muchos-a-muchos. Un event bus puede servir como ambos.

P: ¿Cuál es la diferencia entre Mediator y Facade? R: Facade proporciona una interfaz simplificada a un subsistema. Mediator coordina la comunicación entre objetos pares. Facade es sobre simplificar acceso; Mediator es sobre desacoplar pares.