viernes, 22 de mayo de 2009

DECORATOR

Nombre
Decorator.

Clasificación

Estructural.

Intención
Agrega responsabilidad a una clase dinámi-camente. Decorator agrega funcionalidad a una clase de forma flexible.

También conocido como
Wrapper (envoltura).

Motivo
Algunas veces necesitamos agregar funcio-nalidad a una subclase específica y no a toda una jerarquía de clases, por ejemplo, adicionar un marco y un scroollbar a una ventana. Estos cambios se pueden realizar utilizando herencia, pero entonces generamos código inflexible, el problema se genera cuando deseamos aplicar las funcionalidades agregadas; el cliente no puede decidir cuándo y cómo utilizar la nueva funcionalidad dinámicamente sino que tiene que agregar una subclase para cada cambio que quiera hacer a cada clase. Si pensamos en la ventana, se debe crear una subclase para adicionar un marco, para el scroollbar, para los dos simultáneamente, y para ninguno de los dos. Deacorator ofrece una solución flexible a este problema agregando el componente (en este caso es la vetana) a otro objeto que se encarga de agregar las extensiones (el marco y el scroollbar).

Aplicabilidad
Use decorator:

• Para agregar funcionalidad a un objeto dinámicamente y transparentemente, es-to es, sin afectar a los otros objetos.
• Para manejar responsabilidades que pueden ser eliminadas.
• Para evitar una jerarquía de clases ex-tensa que se hace inmanejable.

Estructura













Participantes
• Component: Define la interfaz para com-ponentes que pueden agregan funciona-lidad.
• ConcreteComponent: define los objetos que pueden agregar funcionalidad diná-micamente.
• Decorator: mantiene la referencia a un componente y define una interfaz compatible con component.
• ConcretDecorator: agrega responsabili-dades al componente.

Colaboración
Decorator envía una petición a su componen-te objeto, y opcionalmente puede agregar responsabilidades antes o después de la pe-tición.

Consecuencias

• Más flexible que la herencia estática: responsabilidades pueden añadirse y eliminarse en tiempo de ejecución. Facili-tan agregar una opción varias veces.
• Diferentes decoradores pueden ser co-nectados a un mismo objeto.
• Reduce el número de propiedades en las clases de la parte alta de la jerarquía.
• Es simple añadir nuevos decoradores de forma independiente a las clases que ex-tienden.
• Un objeto decorador tiene diferente OID al del objeto que decora.
• Sistemas con muchos y pequeños obje-tos.

Implementación
Varias situaciones deben ser consideradas cuando se desea implementar Decorator.
• Conformidad de interfaces. La interfaz de un objeto decorator debe ajustarse a la interfaz del objeto que decora.
• Omitir la clase abstracta decorator. No hay necesidad de agregar una clase abs-tracta decorator cuando sólo hay que manejar una responsabilidad.
• Mantener los componentes de las clases ligeros. Tanto el componente como los decoradores deben descender de una clase común ligera. Debe ser una interfaz y no un almacén de datos.
• Si la clase componente no es lo suficien-temente ligera es mejor utilizar strategy.

Código ejemplo

//clase que define la interfaz para el componente al

//que se le agrega responsabilidad dinámicamente. (component)

import java.awt.Graphics;

import java.awt.Image;

public interface Dibujo {

public Image getDibujo(Graphics g);

}

//Clase que implementa dibujo (ConcreteComponent)

import java.awt.Graphics;

import java.awt.Image;

import java.awt.image.BufferedImage;

import java.io.IOException;

import javax.imageio.ImageIO;

public class DibujoConcretoA implements Dibujo {

private BufferedImage imagen;

public DibujoConcretoA(){

try{

imagen= ImageIO.read(getClass().getClassLoader().getResource("Dibujo1.jpg"));

}catch (IOException e){

System.out.println("Error al leer la margen");

}

}

public Image getDibujo(Graphics g) {

g.drawString("DibujoConcretoA", 130,130);

return imagen;

}

}

//Clase abstracta que define a las decoraciones (Decorator)

import java.awt.Graphics;

import java.awt.Image;

public abstract class Decorator implements Dibujo {

private Dibujo unDibujo=null;

public Decorator(Dibujo d){

unDibujo= d;

}

public Image getDibujo(Graphics g) {

return unDibujo.getDibujo(g);

}

}

//Decorador que le agrega un marco al dibujo (ConcretDecorator)

import java.awt.Graphics;

import java.awt.Image;

public class AgregarMarco extends Decorator {

public AgregarMarco(Dibujo d) {

super(d);

}

public Image getDibujo(Graphics g){

agregarMarco(g);

return super.getDibujo(g);

}

public void agregarMarco(Graphics g){

g.drawRect(20, 90, 318, 288);

}

}

//decorador que agrega fondo al dibujo (ConcrtetDecorator)

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Image;

public class agregarFondo extends Decorator{

public agregarFondo(Dibujo d) {

super(d);

}

public Image getDibujo(Graphics g){

agregaFondo(g);

return super.getDibujo(g);

}

public void agregaFondo(Graphics g){

g.setColor(new Color(204,203,153));

g.fillRect(20, 90, 320, 290);

g.setColor(Color.BLACK);

}

}

//Cliente que utiliza el dibujo y puede agregar opcionalmente

//decoraciones.

import javax.swing.JPanel;

import javax.swing.JButton;

import javax.swing.JFrame;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.Image;

import java.awt.Color;

import java.awt.Graphics;

public class Cliente extends JFrame implements ActionListener{

private JPanel panel;

private JButton figura;

private JButton marco;

private JButton fondo;

private JButton todo;

private Image imagen=null;

private Dibujo dibujo= new DibujoConcretoA();

private Dibujo miDibujo=dibujo;

private Decorator d1= null;

private Decorator d2=null;

private Decorator d3=null;

public Cliente(){

panel = new JPanel();

figura= new JButton("Figura");

marco=new JButton("Marco");

fondo= new JButton("Fondo");

todo= new JButton("Todo");

this.setTitle("Dibujo");

this.setSize(360,400);

this.setResizable(false);

this.setVisible(true);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

panel=(JPanel)this.getContentPane();

panel.setLayout(null);

panel.add(figura);

panel.add(marco);

panel.add(fondo);

panel.add(todo);

figura.setBounds(10, 20, 70, 20);

marco.setBounds(100, 20, 70, 20);

fondo.setBounds(190, 20, 70, 20);

todo.setBounds(280, 20, 70, 20);

figura.addActionListener(this);

marco.addActionListener(this);

fondo.addActionListener(this);

todo.addActionListener(this);

d1= new AgregarMarco(dibujo);

d2= new agregarFondo(dibujo);

d3= new agregarFondo(d1);

}

public static void main(String args[]){

new Cliente();

}

public void paint(Graphics g){

g.setColor(Color.white);

g.fillRect(20, 90, 320 ,290);

g.setColor(Color.BLACK);

imagen=miDibujo.getDibujo(g);

g.drawImage(imagen,80,150, 200,200,this);

}

public void actionPerformed(ActionEvent e) {

if(e.getSource()==figura){

miDibujo=dibujo;

}

if(e.getSource()==marco){

miDibujo=d1;

}

if(e.getSource()==fondo){

miDibujo=d2;

}

if(e.getSource()==todo){

miDibujo=d3;

}

repaint();

}

}



Usos conocidos
• Muchas barras de herramientas de inter-faces de usuario orientado a objetos utilizan, decorator para agregar adornos a sus componentes.
• También es usado en los flujos de datos de la entrada y salida, de un lenguaje. Esto es para agregar responsabilidades al flujo, como compresión o conversión a un sistema de caracteres.

Patrones relacionados

• Adapter se diferencia de decorator, en que, define una nueva interfaz a un obje-to, mientras descorator agrega respon-sabilidades a un objeto, pero no cambia su interfaz.
• Decorator, puede confundirse como una derivación de un composite con un obje-to complejo, pero decorator agrega fun-cionalidad y su intención no es agregar objetos.
• Decorator permite cambiar la parte exte-rior de un objeto (skin-piel), mientras strategy cambia el mecanismo interno, su comportamiento. Así los dos son patrones que permiten cambiar un bojeto.

Referencias bibliográficas

[1] Erich Gamma et al, Elements of reusable object-oriented software.
[2] Steve Holzner, Design patterns for dummies, Wiley Publishing Inc, Indianapolis, EEUU, 2006, 339.
[3] Jesús García Molina, Análisis y diseño de software - Patrones de diseño, dis.um.es/~jmolina/astema3.


1 comentario:

Anónimo dijo...

de favor coloca la imagen q pides en la clase dibujo