Diseño de software

Patrón Mediator en Swift: guía completa (delega la comunicación entre objetos)

Si has hecho crecer un poco una app de iOS, probablemente te hayas encontrado con este momento.

4 min de lectura
Imagen de portada de Patrón Mediator en Swift: guía completa (delega la comunicación entre objetos)

Si has hecho crecer un poco una app de iOS, probablemente te hayas encontrado con este momento.

Una pantalla tiene cinco o seis vistas: si cambia A, también debe cambiar B; y si cambia B, hay que ajustar C.

En poco tiempo, las vistas se referencian directamente y quedan enredadas como un ovillo.

Eso es precisamente lo que ayuda a organizar el patrón Mediator.

El patrón Mediator en Swift reduce el acoplamiento al hacer que los objetos se comuniquen solo con un Mediator, sin referenciarse directamente entre sí.

En este artículo explicamos qué es el patrón Mediator, cuándo conviene usarlo y cómo implementarlo en Swift con código de ejemplo.


¿Qué es el patrón Mediator?

En una frase:

Coloca un Mediator entre los objetos que necesitan comunicarse y haz que toda conversación pase por él.

Piensa en una torre de control aeroportuaria.

Si los aviones se dijeran por radio «aterriza tú primero» y «yo voy primero», ocurriría un accidente grave.

Por eso, cada avión habla únicamente con la torre, que organiza el orden.

Aquí, los aviones son los objetos del código y la torre es el Mediator.

El patrón Mediator resuelve principalmente lo siguiente:

  • Eliminar referencias directas: el objeto A ya no necesita conocer individualmente B, C y D
  • Centralizar la lógica de comunicación: las reglas de interacción complejas se reúnen en un Mediator
  • Mejorar la reutilización: los objetos independientes se pueden reutilizar fácilmente en otras pantallas

¿Cuándo conviene usar el patrón Mediator?

No es adecuado para todas las situaciones. Me planteo usarlo cuando aparecen señales como estas.

Cuando los objetos saben demasiado unos de otros; al abrir una clase aparece una larga cadena de referencias a otros objetos.

Otra señal es tener que modificar varios objetos relacionados a la vez para cambiar una sola parte de la lógica.

Estos son algunos usos habituales:

Situación Ejemplo
UI de pantalla compleja Varios botones y etiquetas reaccionan en cadena según los valores del formulario
Coordinación de componentes Retransmisión de mensajes entre participantes de una sala de chat
Control del flujo de trabajo Gestión del estado de las vistas en cada etapa del pago

En cambio, si solo hay dos o tres objetos y la relación es sencilla, es mejor no usarlo.

El Mediator podría crecer sin necesidad y convertirse en un «God Object».


¿Cómo se implementa el patrón Mediator en Swift?

Veamos un ejemplo de sala de chat. Los participantes intercambian mensajes a través de la sala (el Mediator), en lugar de enviárselos directamente.

Primero definimos el protocolo que debe seguir el Mediator y los participantes.

// Reglas que debe seguir el Mediator
protocol ChatMediator {
    func send(_ message: String, from user: User)
    func add(_ user: User)
}

La clave es que cada participante solo conoce al Mediator y no referencia directamente a los demás.

class User {
    let name: String
    weak var mediator: ChatMediator?  // Evitar referencias circulares

    init(name: String) { self.name = name }

    func send(_ text: String) {
        mediator?.send(text, from: self)  // Delegar en el Mediator
    }
    func receive(_ text: String) {
        print("\(name) Recibido: \(text)")
    }
}

Por último, el Mediator se encarga de las reglas reales de entrega: difunde el mensaje solo a quienes no lo enviaron.

class ChatRoom: ChatMediator {
    private var users: [User] = []
    func add(_ user: User) { users.append(user); user.mediator = self }
    func send(_ message: String, from user: User) {
        users.filter { $0 !== user }
             .forEach { $0.receive("[\(user.name)] \(message)") }
    }
}

Aunque aumente el número de usuarios, no hay que tocar la clase User. Solo ChatRoom conoce las reglas de entrega.

Todos conocen solo ChatRoom; no se conocen entre sí
Todos conocen solo ChatRoom; no se conocen entre sí
Ejecuta el código de ejemplo y escribe junto con él para entenderlo de inmediato
Ejecuta el código de ejemplo y escribe junto con él para entenderlo de inmediato

Mediator frente a Observer: ¿en qué se diferencian?

Mucha gente confunde estos dos patrones.

La diferencia, resumida, es la siguiente.

Categoría Mediator Observer
Dirección Comunicación muchos a muchos centralizada Notificación uno a muchos (publicación-suscripción)
Relación Los objetos interactúan mediante el Mediator El objeto observado notifica a los observadores
Enfoque Coordinación mutua compleja Propagación de cambios de estado

En pocas palabras, Observer anuncia unilateralmente: «¡He cambiado!»

Mediator decide «¿quién debe hacer qué en esta situación?» y coordina los objetos.

En Swift, Combine y NotificationCenter se parecen más a la familia Observer; Mediator suele implementarse directamente.


Preguntas frecuentes (Q&A)

P. ¿Qué hago si el Mediator crece demasiado?

Como la lógica se concentra allí, el Mediator puede inflarse fácilmente. Divídelo en varios Mediators por funcionalidad o separa la lógica interna en helpers independientes.

P. ¿Hay que usar weak obligatoriamente?

Sí. Si los participantes y el Mediator se referencian fuertemente, las referencias circulares provocan fugas de memoria. Haz weak uno de los lados, como en el ejemplo.

P. ¿También se puede usar con SwiftUI?

Sí. A menudo, un ViewModel actúa en la práctica como Mediator entre las vistas. Puedes coordinar de forma natural el estado de varias vistas mediante un único ViewModel.

Dibujar un Mediator y ordenar las relaciones me aclaró la mente
Dibujar un Mediator y ordenar las relaciones me aclaró la mente

Si tus objetos están tan enredados que da miedo tocar el código, prueba a incorporar el patrón Mediator.

Basta con establecer un Mediator para aligerar mucho cada objeto y añadir funcionalidades después con más tranquilidad.

Te recomiendo aplicar el código de ejemplo de hoy tal cual en un proyecto pequeño. Al escribirlo tú mismo, todo encaja. 😊

Seguir leyendo