informaticaPC

Patrones de Diseño Software

Mediator

Una de las ventajas que ofrece la programación orientada a objetos (POO) es la posibilidad de reutilizar el código fuente, pero a medida que creamos objetos que se interrelacionan entre sí es menos probable que un objeto pueda funcionar sin la ayuda de otros.

Para evitar esto podemos utilizar el patrón Mediator, en el que se define una clase que hará de mediadora encapsulando la comunicación entre los objetos, evitándose con ello la necesidad de que lo hagan directamente entre sí.

Veámoslo mejor a continuación con un ejemplo sencillo.

Main.java:

package Mediator1;

public class Main
{
    public static void main(String[] args)
    {
        // Crear el objeto centralizador de la comunicación
        Mediador m = new Mediador();

        // Crear los objetos que participarán en la comunicación
        Colega cc1 = new ColegaConcreto1( m );
        Colega cc2 = new ColegaConcreto2( m );
        Colega cc3 = new ColegaConcreto3( m );

        // Agregarlos al objeto centralizador
        m.agregarColega( cc1 );
        m.agregarColega( cc2 );
        m.agregarColega( cc3 );

        // Provocar un cambio en un uno de los elementos
        cc2.comunicar("ColegaConcreto2 ha cambiado!");
    }
}

IMediador.java:

package Mediator1;

public interface IMediador
{
    public void enviar(String mensaje, Colega emisor);
}

Mediador.java:

package Mediator1;

import java.util.ArrayList;

public class Mediador implements IMediador
{
    private ArrayList<Colega> colegas;

    // -------------------------------

    public Mediador()
    {
        this.colegas = new ArrayList<Colega>();
    }

    // -------------------------------

    public void agregarColega(Colega colega)
    {
        this.colegas.add( colega );
    }

    // ------------------------------

    @Override
    public void enviar(String mensaje, Colega originator)
    {
        for( Colega colega : colegas )
        {
            if( colega != originator )
            {
                colega.recibir( mensaje );
            }
        }
    }
}

Colega.java:

package Mediator1;

public abstract class Colega
{
    protected IMediador mediador;

    // -------------------------------

    public IMediador getMediador()
    {
        return this.mediador;
    }

    // -------------------------------

    public void setMediador( IMediador m )
    {
        this.mediador = m;
    }

    // -------------------------------

    public void comunicar(String mensaje)
    {
        this.getMediador().enviar(mensaje, this);
    }

    // -------------------------------

    // Método a implementar por las clases que hereden
    public abstract void recibir(String mensaje);
}

ColegaConcreto1.java:

package Mediator1;

public class ColegaConcreto1 extends Colega
{
    public ColegaConcreto1(IMediador m) {
        this.setMediador( m );
    }

    // -------------------------------

    @Override
    public void recibir(String mensaje)
    {
        System.out.println( "ColegaConcreto1: " + mensaje );
    }
}

ColegaConcreto2.java:

package Mediator1;

public class ColegaConcreto2 extends Colega
{
    public ColegaConcreto2(IMediador m) {
        this.setMediador( m );
    }

    // -------------------------------

    @Override
    public void recibir(String mensaje)
    {
        System.out.println( "ColegaConcreto1: " + mensaje );
    }
}

ColegaConcreto3.java:

package Mediator1;

public class ColegaConcreto3 extends Colega
{
    public ColegaConcreto3(IMediador m) {
        this.setMediador( m );
    }

    // -------------------------------

    @Override
    public void recibir(String mensaje)
    {
        System.out.println( "ColegaConcreto1: " + mensaje );
    }
}

Al ejecutarlo veríamos lo siguiente:

Ejemplo de Mediator

EXPLICACIÓN:

  • Al inicio del programa creamos el objeto de tipo Mediador encargado de dirigir la comunicación, y los de tipo Colega que participarán en la misma.
  • A continuación se provoca un cambio en uno de los objetos de tipo Colega a través del método comunicar() (implementado en la clase abstracta de la que heredan).
  • En dicho método se envían los datos (junto con una referencia al objeto modificado) al objeto de tipo Mediador para que a su vez los reenvíe a los demás objetos que participan en la comunicación (observa que no los envía también al objeto que sufrió el cambio).

Veamos otro ejemplo de implementación de este patrón de diseño.

Main.java:

package Mediator2;

public class Main
{
    public static void main( String[] args )
    {
        // Crear los objetos que participarán en la comunicación
        BotonHola hola     = new BotonHola();
        BotonAdios adios   = new BotonAdios();
        BotonBorrar borrar = new BotonBorrar();
        CuadroTexto texto  = new CuadroTexto();

        // Crear el objeto mediador de la comunicación y agregarle los otros objetos
        Mediador m = new Mediador( hola, adios, borrar, texto );

        // Definir en cada objeto el mediador usado en la comunicación
        hola.setMediador(m);
        adios.setMediador(m);
        borrar.setMediador(m);
        texto.setMediador(m);

        // Provocar clics en los botones
        hola.clickHola();
        adios.clickAdios();
        borrar.clickBorrar();
        hola.clickHola();
    }
}

Mediador.java:

package Mediator2;

public class Mediador
{
    private BotonHola   hola;
    private BotonAdios  adios;
    private BotonBorrar borrar;
    private CuadroTexto texto;

    // -------------------------------

    public Mediador( BotonHola hola,
                     BotonAdios adios,
                     BotonBorrar borrar,
                     CuadroTexto texto
                    )
    {
        this.hola   = hola;
        this.adios  = adios;
        this.borrar = borrar;
        this.texto  = texto;
    }

    // -------------------------------

    public void clickHola()
    {
        this.texto.setTexto("Hola");
    }

    // -------------------------------

    public void clickAdios()
    {
        this.texto.setTexto("Adios");
    }

    // -------------------------------

    public void clickBorrar()
    {
        this.texto.setTexto(null);
    }
}

Componente.java (un Colega en el diagrama anterior):

package Mediator2;

public class Componente
{
    protected Mediador m;

    // -------------------------------

    public Componente() {
    }

    // -------------------------------

    public Mediador getMediador()
    {
        return this.m;
    }

    // -------------------------------

    public void setMediador( Mediador m )
    {
        this.m = m;
    }
}

BotonHola.java (un ColegaConcreto en el diagrama anterior):

package Mediator2;

public class BotonHola extends Componente
{
    public BotonHola() {
    }

    // -------------------------------

    public void clickHola()
    {
        this.getMediador().clickHola();
    }
}

BotonAdios.java (un ColegaConcreto en el diagrama anterior):

package Mediator2;

public class BotonAdios extends Componente
{
    public BotonAdios() {
    }

    // -------------------------------

    public void clickAdios()
    {
        this.getMediador().clickAdios();
    }
}

BotonBorrar.java (un ColegaConcreto en el diagrama anterior):

package Mediator2;

public class BotonBorrar extends Componente
{
    public BotonBorrar() {
    }

    // -------------------------------

    public void clickBorrar()
    {
        this.getMediador().clickBorrar();
    }
}

CuadroTexto.java (un ColegaConcreto en el diagrama anterior):

package Mediator2;

public class CuadroTexto extends Componente
{

    public CuadroTexto() {
    }

    // -------------------------------

    public void setTexto(String texto)
    {
        if( texto == null )
        {
            System.out.println( "El cuadro de texto está vacío" );
        }
        else
        {
            System.out.println( texto );
        }
    }

}

Al ejecutarlo veríamos lo siguiente:

Ejemplo de Mediator

EXPLICACIÓN:

  • En el programa principal creamos el objeto de tipo Mediador y los de tipo Componente que participarán en la misma (observa que en este caso no es necesario crear la interface de IMediador ya que como se indica en el libro de GoF: 'no es necesario cuando los colegas sólo trabajan con un mediador').
  • En dicha clase centralizadora se implementan diferentes métodos para procesar acciones dependiendo del componente que haya sido modificado en cada caso (el botón sobre el que se haga clic).
  • A continuación se simulan clics en los diferentes botones, causando que varíe el contenido mostrado por el componente CuadroTexto.
Información

El patrón de diseño Mediator es parecido al patrón Observer (en el que se define una dependencia de tipo 'uno a muchos' entre objetos de forma que cuando el que es observado cambia lo notifica al resto), sin embargo en el primero una clase central encapsula y dirige la comunicación generada entre los demás objetos.

Primera página Anterior Siguiente Última página
Usamos cookies para ofrecerte una experiencia mejorada, el continuar navegando supone que aceptas su uso