informaticaPC

Patrones de Diseño Software

Decorator

Sencillo e interesante patrón que permite añadir funcionalidades a un objeto en aquellos casos en los que no sea necesario o recomendable hacerlo mediante herencia:

Patrón Decorator en UML

A continuación mostramos uno de los ejemplos clásicos usados para explicarlo: crear una clase que dibuje ventanas básicas, y utilizar el patrón para agregar barras de desplazamiento sólo a algunas de ellas.

Main.java:

package estructurales.decorator.decorator01;

public class Main
{
    public static void main(String[] args)
    {
        IVentana ventana1 = new Ventana();
        ventana1.dibujar(50, 70);

        System.out.println("-----");

        // Dibujar una ventan que tenga la barra de desplazamiento vertical
        IVentana ventana2 = new DecoradorDesplazamientoVert( new Ventana() );
        ventana2.dibujar(300, 200);

        System.out.println("-----");

        // Dibujar una ventan que tenga la barra de desplazamiento horizontal
        IVentana ventana3 = new DecoradorDesplazamientoHoriz( new Ventana() );
        ventana3.dibujar(400, 300);

        System.out.println("-----");

        // Dibujar una ventan que tenga las barras de desplazamientos horizontal y vertical
        IVentana ventana4 = new DecoradorDesplazamientoVert( new DecoradorDesplazamientoHoriz( new Ventana() ) );
        ventana4.dibujar(100, 120);
    }
}

IVentana.java (IComponente según el diagrama anterior):

package estructurales.decorator.decorator01;

public interface IVentana
{
    public void dibujar(int columna, int fila);
}

Ventana.java (ComponenteConcreto según el diagrama anterior):

package estructurales.decorator.decorator01;

public class Ventana implements IVentana
{
    public Ventana() {
    }

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

    @Override
    public void dibujar(int col, int fila)
    {
        System.out.println("Dibujada ventana básica en [" + col + "], [" + fila + "]" );
    }
}

DecoradorDesplazamiento.java (Decorador según el diagrama anterior):

package estructurales.decorator.decorator01;

public abstract class DecoradorDesplazamiento implements IVentana
{
    protected IVentana v;

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

    public DecoradorDesplazamiento( IVentana v )
    {
        this.setVentana( v );
    }

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

    public IVentana getVentana()
    {
        return this.v;
    }

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

    public void setVentana( IVentana v )
    {
        this.v = v;
    }

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

    @Override
    public void dibujar(int col, int fila)
    {
        this.getVentana().dibujar(col, fila);
    }
}

DecoradorDesplazamientoHoriz.java (un DecoradorConcreto según el diagrama anterior):

package estructurales.decorator.decorator01;

public class DecoradorDesplazamientoHoriz extends DecoradorDesplazamiento
{
    public DecoradorDesplazamientoHoriz( IVentana v )
    {
        super( v );
    }

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

    @Override
    public void dibujar(int col, int fila)
    {
        // Dibujar la ventana
        this.getVentana().dibujar(col, fila);

        // Agregar barra de desplazamiento
        this.dibujarBarraDespHorizontal();
    }

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

    private void dibujarBarraDespHorizontal()
    {
        System.out.println("Agregada barra de desplazamiento horizontal");
    }
}

DecoradorDesplazamientoVert.java (un DecoradorConcreto según el diagrama anterior):

package estructurales.decorator.decorator01;

public class DecoradorDesplazamientoVert extends DecoradorDesplazamiento
{
    public DecoradorDesplazamientoVert( IVentana v )
    {
        super( v );
    }

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

    @Override
    public void dibujar(int col, int fila)
    {
        // Dibujar la ventana
        this.getVentana().dibujar(col, fila);

        // Agregar barra de desplazamiento
        this.dibujarBarraDespVertical();
    }

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

    private void dibujarBarraDespVertical()
    {
        System.out.println("Agregada barra de desplazamiento vertical");
    }
}

Al ejecutarlo obtendríamos como resultado:

Ejemplo

EXPLICACIÓN:

  • La clase abstracta DecoradorDesplazamiento es la encargada de definir las funcionalidades que se podrán agregar a objetos que (como ella misma) implementan la interface IVentana.
  • Contiene además una referencia a otro objeto (asignada en el constructor) de tipo IVentana, y en el método dibujar() que debe implementar simplemente se llama al método del mismo nombre en dicho objeto.
  • Los objetos que heredan de DecoradorDesplazamiento llaman al constructor de su clase padre pasándole como parámetro el objeto de tipo IVentana recibido en su propio constructor (para guardar una referencia al mismo y así poder acceder a él en otro momento).
  • Cuando se llama al método dibujar() de dichos objetos de tipo DecoradorDesplazamiento se crea la ventana básica, y a continuación a un método propio para agregar la barra de desplazamiento deseada en cada caso.
  • Al iniciarse el programa se crea una ventana básica y luego otras que contendrán una o ambas barras de desplazamiento según cada caso (observa cómo en el tercer caso se encadenan los contructores para agregar ambas barras de desplazamiento).
Primera página Anterior Siguiente Última página
Usamos cookies para ofrecerte una experiencia mejorada, el continuar navegando supone que aceptas su uso