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:
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:
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.

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.