lunes, 4 de mayo de 2015

Mediator

Mediator

Propósito

Define un objeto que encapsula cómo interactúan un conjunto de objetos. Promueve un bajo acoplamiento al evitar que los objetos se refieran unos a otros explícitamente, y permite variar la interacción entre ellos de forma independiente.

Motivación

Cuando muchos objetos interactúan con otros objetos, se puede formar una estructura muy compleja, con objetos con muchas conexiones con otros objetos. En un caso extremo cada objeto puede conocer a todos los demás objetos. Para evitar esto el patrón Mediator encapsula el comportamiento de todo un conjunto de objetos en un solo objeto.
Los objetos envían y reciben peticiones a través del mediador, este patrón implementa el comportamiento cooperativo encaminando esas peticiones a los objetos apropiados.

Aplicabilidad

Utilizaremos el patrón Mediator cuando:
  • Un conjunto grande de objetos se comunica de una forma bien definida, pero compleja.
  • Dificultad para reutilizar objetos ya que nos referimos a varios objetos para comunicarnos.
  • El comportamiento de muchos objetos que esta distribuido entre varias clases, puede resumirse en una o varias por subclasificación.
Estructura
Participantes
  • Mediator: define una interface para comunicarse con los objetos colegas.
  • ConcreteMediator: Implementa el comportamiento cooperativo entre los colegas (como se comunican entre ellos). Además los conoce y mantiene.
  • Colleagues classes: Cada colega conoce su mediador, y usa a este para comunicarse con otros colegas.
Colaboraciones

Los objetos (Colegas) envían y reciben requerimientos (requests) de un objeto mediador. El mediador implementa como se comunican los objetos.

Consecuencias

Ventajas e inconvenientes del patrón Mediator:

  • Reduce herencia. Con una subclase llamada Mediador cambiamos el comportamiento, que de otra manera estaría distribuido en varios objetos.
  • Desacopla a los objetos. El patrón Mediator promueve bajar el acoplamiento entre objetos. Se puede variar y rehusar objetos y mediadores independientemente.
  • Simplifica la comunicación entre objetos. Los objetos que se comunican de la forma "muchos a muchos" puede ser remplazada por una forma "uno a muchos" que es menos compleja y más elegante. Además esta forma de comunicación es más fácil de entender.Abstrae como los objetos cooperan. Haciendo a la mediación un concepto independiente y encapsulándolo en un objeto permite enfocar como los objetos interactúan. Esto ayuda a clarificar como los objetos se relacionan en un sistema.
  • Centraliza el control. El mediador es el que se encarga de comunicar a los objetos, este puede ser muy complejo, difícil de entender y modificar.
Implementación

Es importante tener en cuenta en la implementación de este patrón:

  • Omitir la clase abstracta Mediator. No es necesario crear una clase abstracta Mediador cuando los objetos solo trabajan con un mediador. El acoplamiento abstracto de dicha clase permite que los objetos trabajen con diferentes subclases Mediator y viceversa.
  • Comunicación Objeto y Mediador. Los objetos se comunican su mediador cuanto tiene lugar un evento. Las clases de objetos cada vez que cambian su estado envían notificaciones al mediador. El mediador responde propagando los efectos de dichos eventos a los otros objetos.Otra forma define al Mediador una interfaz de notificación especializada que permite a los objetos ser más directos en su comunicación.
Código de ejemplo

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

//Interfaz Amigo
interface Command {
    void execute();
}

//Mediador Abstracto
interface IMediator {
    void book();
    void view();
    void search();
    void registerView(BtnView v);
    void registerSearch(BtnSearch s);
    void registerBook(BtnBook b);
    void registerDisplay(LblDisplay d);
}

//Mediador Concreto
class Mediator implements IMediator {

    BtnView btnView;
    BtnSearch btnSearch;
    BtnBook btnBook;
    LblDisplay show;

    //....
    void registerView(BtnView v) {
        btnView = v;
    }

    void registerSearch(BtnSearch s) {
        btnSearch = s;
    }

    void registerBook(BtnBook b) {
        btnBook = b;
    }

    void registerDisplay(LblDisplay d) {
        show = d;
    }

    void book() {
        btnBook.setEnabled(false);
        btnView.setEnabled(true);
        btnSearch.setEnabled(true);
        show.setText("booking...");
    }

    void view() {
        btnView.setEnabled(false);
        btnSearch.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("viewing...");
    }

    void search() {
        btnSearch.setEnabled(false);
        btnView.setEnabled(true);
        btnBook.setEnabled(true);
        show.setText("searching...");
    }

}

//Un amigo concreto
class BtnView extends JButton implements Command {

    IMediator med;

    BtnView(ActionListener al, IMediator m) {
        super("View");
        addActionListener(al);
        med = m;
        med.registerView(this);
    }

    public void execute() {
        med.view();
    }

}

//Un amigo concreto
class BtnSearch extends JButton implements Command {

    IMediator med;

    BtnSearch(ActionListener al, IMediator m) {
        super("Search");
        addActionListener(al);
        med = m;
        med.registerSearch(this);
    }

    public void execute() {
        med.search();
    }

}

//Un amigo concreto
class BtnBook extends JButton implements Command {

    IMediator med;

    BtnBook(ActionListener al, IMediator m) {
        super("Book");
        addActionListener(al);
        med = m;
        med.registerBook(this);
    }

    public void execute() {
        med.book();
    }

}

class LblDisplay extends JLabel {

    IMediator med;

    LblDisplay(IMediator m) {
        super("Just start...");
        med = m;
        med.registerDisplay(this);
        setFont(new Font("Arial", Font.BOLD, 24));
    }

}

class MediatorDemo extends JFrame implements ActionListener {

    IMediator med = new Mediator();

    MediatorDemo() {
        JPanel p = new JPanel();
        p.add(new BtnView(this, med));
        p.add(new BtnBook(this, med));
        p.add(new BtnSearch(this, med));
        getContentPane().add(new LblDisplay(med), "North");
        getContentPane().add(p, "South");
        setSize(400, 200);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent ae) {
        Command comd = (Command) ae.getSource();
        comd.execute();
    }

    public static void main(String[] args) {
        new MediatorDemo();
    }

}

Usos conocidos

El Mediator es comúnmente usado en el desarrollo de aplicaciones que poseen varios componentes dentro de las interfaces gráficas que poseen.
También aparece otra aplicación en el framework de dibujo Unidraw

Patrones relacionados

Un patrón muy parecido a éste es el Facade que se diferencia en que abstrae un sistema de objetos proporcionado una interfaz más conveniente, utilizando un protocolo unidireccional (Fachada realiza solo peticiones a las clases del subsistema pero no a la inversa), mientras que el Mediator usa un protocolo multidireccional.
Con el patrón Observer los objetos pueden comunicarse con el mediador.

Referencias
  • Design Patterns Elements of Reusable Object-Oriented Software, GoF.
  • http://dc.exa.unrc.edu.ar/nuevodc/materias/sistemas/2007/Patrones/1181918751/MediatorRes2.pdf
  • http://kybele.escet.urjc.es/documentos/SI/Patrones/14_Mediator.ppt

No hay comentarios:

Publicar un comentario