jueves, 14 de abril de 2016

Patrón Decorator

Objetivo:
Agregar a un objeto ya existente nuevas funcionalidades. Viene a satisfacer ese principio SOLID  Open Closed Principle "Abierto para extencion, cerrado para modificacion".

Definición:
El patrón decorator permite añadir responsabilidades a objetos concretos de forma dinámica. Los decoradores ofrecen una alternativa más flexible que la herencia para extender las funcionalidades.
Es conocido como Wrapper (igual que el patrón Adapter).
A veces se desea adicionar responsabilidades a un objeto pero no a toda la clase. Las responsabilidades se pueden adicionar por medio de los mecanismos de Herencia, pero este mecanismo no es flexible porque la responsabilidad es adicionada estáticamente. La solución flexible es la de rodear el objeto con otro objeto que es el que adiciona la nueva responsabilidad. Este nuevo objeto es el Decorator.

¿Cuándo se debe utilizar este Patrón?

  • Hay una necesidad de extender la funcionalidad de una clase, pero no hay razones para extenderlo a través de la herencia.
  • Se quiere agregar o quitar dinámicamente la funcionalidad de un objeto.

Ejemplo

Se propone el ejemplo de una Cafetería, Donde tenemos una clase abstracta BEBIDA  y tenemos varias clases concretas que extienden de esta clase abstracta.



Pero imaginen ¿que pasaría en el momento en que empecemos a combinar estas bebidas? es decir si a ese Café_Expreso le agregamos leche, crema, canela, azúcar etc. harían bien especifica esa bebida, pero nos encontraremos con una situación, algo así:


Tendremos un esquema de clases, que parecería algo anárquico tal como vemos en la imagen anterior, siendo un conjunto innumerable de mezclas terminando ser inmanejable. El Patrón Decorator propone, tomar un tipo de café bien especifico y a ese café agregarle elementos adicionales.



Esto se logra con una arquitectura como la que podemos ver en la siguiente imagen.

Vemos la clase BEBIDA de la cual extienden unas bebidas especificas, de esa misma clase BEBIDA extiende el decorador que serian esas características que le agregaremos a cada bebida, pero fijémonos bien en esta estructura de clases, que estamos viendo dos tipos de relaciones que existen entre la clase BEBIDA y la clase ADICIONALES_DECORATOR ambas abstractas, una relacion de Herencia y otra de Asociación que significa que la clase ADICIONALES_DECORATOR tiene  un atributo de tipo BEBDA.

Solución

Creamos la clase Bebidas Abstracta como dijimos anteriormente. le agregamos los métodos públicos y abstractos que seria getPrecio y getDescripcion

Creamos las clases mas representativas, esas clases bien especificas, que heredarian de la clase Bebidas.

Es aquí donde empezamos a darle solución al problema, creando la clase abstracta Adicionales_Abstracto en la cual existe la doble relación con  Bebidas, heredando de esta y ala vez teniendo una Asociación por medio del  atributo de tipo Bebidas.

Por ultimo las clases Adicionales que extienden de Adicionales_Abstracto y la implementacion del MAIN para ver su funcionamiento.

Descarga el Proyecto Aqui

Participantes

Consecuencias

  • Es más flexible que la herencia: utilizando diferentes combinaciones de unos pocos tipos distintos de objetos decorator, se puede crear muchas combinaciones distintas de comportamientos. Para crear esos diferentes tipos de comportamiento con la herencia se requiere que definas muchas clases distintas.
  • Evita que las clases altas de la jerarquía estén demasiado cargadas de funcionalidad.
  • Un componente y su decorador no son el mismo objeto.
  • Provoca la creación de muchos objetos pequeños encadenados, lo que puede llegar a complicar la depuración.
  • La flexibilidad de los objetos decorator los hace más propenso a errores que la herencia. Por ejemplo, es posible combinar objetos decorator de diferentes formas que no funcionen, o crear referencias circulares entre los objetos decorator.





















0 comentarios:

Publicar un comentario