Saltar al contenido

Mediator

Un patrón de comportamiento: los objetos de un grupo se comunican a través de un mediador, en lugar de referenciarse unos a otros.

6 min. de lectura

Mediator es un patrón de comportamiento que reduce las dependencias caóticas entre objetos, obligándolos a comunicarse a través de un objeto mediador en lugar de hacerlo directamente entre sí.

El problema

El formulario de checkout de AndesShop tiene varios campos que se afectan entre sí: elegir envío express deshabilita el pago contra entrega; aplicar un cupón recalcula el total, lo que puede habilitar o deshabilitar ciertos métodos de envío gratuitos; cambiar la dirección puede invalidar un cupón que solo aplica a determinadas zonas. Si cada componente del formulario conoce y llama directamente a los demás para notificarles estos cambios, el formulario termina siendo una red de referencias cruzadas donde tocar un componente obliga a entender cómo afecta a todos los demás.

La solución

Mediator centraliza esa coordinación en un objeto aparte. Cada componente del formulario solo conoce al mediador, nunca a los otros componentes directamente: cuando cambia, se lo informa al mediador, y es el mediador quien decide qué otros componentes tienen que reaccionar y cómo.

Estructura de Mediator: los colleagues no se conocen entre sí, solo conocen al mediator, que centraliza cómo reaccionan unos a otros.

Ejemplo en Java

// El método se llama notifyMediator, no notify: Object.notify() ya existe en
// todo objeto Java para sincronización de hilos, y reusar ese nombre para algo
// completamente distinto confunde a cualquiera que lea la clase después.
interface CheckoutMediator {
    void notifyMediator(Object sender, String event);
}

class ShippingMethodField {
    private final CheckoutMediator mediator;

    public ShippingMethodField(CheckoutMediator mediator) {
        this.mediator = mediator;
    }

    public void selectExpress() {
        mediator.notifyMediator(this, "EXPRESS_SELECTED");
    }
}

class PaymentMethodField {
    public void disableCashOnDelivery() {
        System.out.println("Cash on delivery disabled");
    }
}

// El Mediator concreto: conoce a todos los componentes y decide cómo reaccionan
class CheckoutForm implements CheckoutMediator {
    private final PaymentMethodField paymentField = new PaymentMethodField();

    public void notifyMediator(Object sender, String event) {
        if (sender instanceof ShippingMethodField && event.equals("EXPRESS_SELECTED")) {
            paymentField.disableCashOnDelivery();
        }
        // otras combinaciones sender/event se manejan acá, en un solo lugar
    }
}
// Client code
CheckoutForm form = new CheckoutForm();
ShippingMethodField shippingField = new ShippingMethodField(form);
shippingField.selectExpress(); // dispara la reacción en cadena, coordinada por el mediador

Cuándo usarlo

  • Cuando notás que un grupo de objetos se comunica en una red de referencias directas difícil de seguir, y cambiar uno implica revisar todos los demás.
  • Cuando querés reutilizar un componente individual (un campo de formulario, un widget) en otro contexto, sin arrastrar sus dependencias directas hacia los demás componentes del contexto original.

Cuándo evitarlo

Si solo hay dos o tres objetos con una relación simple y estable entre sí, un Mediator agrega una clase intermedia para un problema que todavía no existe.

Ventajas y desventajas

VentajasDesventajas
Reduce las dependencias directas entre componentes, a cambio de que todos dependan del mediadorEl mediador puede terminar acumulando demasiada lógica y volverse un “objeto todopoderoso”
Facilita reutilizar componentes individuales en otros contextosAgrega un salto extra de indirección para cualquier interacción entre componentes
Centraliza en un solo lugar la lógica de coordinación, más fácil de mantener que reglas dispersas

Relación con otros patrones

  • Se diferencia de Facade en que Facade simplifica el acceso a un subsistema desde afuera; Mediator coordina la comunicación entre pares que ya forman parte del mismo subsistema.
  • Observer a veces se usa para implementar la comunicación entre los componentes y el mediador.

Te sirvió, compartilo

// ¿te sirvió?
// compartilo