Nov 19
Patrón Decorador - Definición, diagramas e implementación
El patrón decorador, (decorator pattern), añade nuevas responsabilidades a un objeto dinamicamente, ofreciendo una alternativa flexible a la herencia.
En otras palabras, es una forma de agregar funcionalidades a una clase, extendiéndola pero sin recurrir a la herencia. ¿Por qué no heredar? Bueno, tal vez no desees dar acceso a toda la clase primaria y entonces sólo se daría acceso a lo necesario.
Veamos un ejemplo simple, tenemos las siguientes clases:
- Persona (ID, Nombre, Apellido y Fecha de Nacimiento)
- Usuario (ID, Nombre, Apellido, Usuario, Passwd)
- Cliente (ID, Nombre, Apellido, Teléfono, Email)
- Cliente VIP (ID, Nombre, Apellido, Teléfono, Email, Nro de Cuenta, Límite de Crédito)
Cómo vemos todos tienen campos comunes a Persona, pero no tienen todos los campos de la clase Persona, por eso no podemos heredar, así es que podremos implementar decoradores para la clase Persona, tendremos los decoradores Usuario, Cliente y Cliente VIP. (Ver figura 1).
Pero si analizamos lo que hemos diseñado hasta el momento podremos observar que Cliente VIP podría llegar a convertirse en un decorador de Cliente, que como recordamos es un decorador de Persona, de esa manera no tendremos que reescribir la lógica detrás de los atributos Teléfono e Email. (Ver figura 2).
La pregunta es cómo decorar una clase, pues a grandes rasgos podríamos decir que se trata de tener una variable privada de la clase a decorar, escribir los métodos o atributos que se deseen publicar de la clase a decorar y luego agregar las decoraciones en nuestra nueva clase, entendiendo por decoraciones los nuevos métodos y/o atributos.
Por último veamos el código correspondiente a nuestras clases.
class Persona { private int ID; private String Nombre; private String Apellido; private Date FechaNac; public int getID() { return ID; } public String getNombre() { return Nombre; } public String getApellido() { return Apellido; } public Date getFechaNac() { return FechaNac; } } class Usuario { private Persona mPersona; private String Usuario; private String Passwd; public int getID() { return mPersona.getID(); } public String getNombre() { return mPersona.getNombre(); } public String getApellido() { return mPersona.getApellido(); } public String getUsuario() { return Usuario; } public String getPasswd() { return Passwd; } } class Cliente { private Persona mPersona; private String Telefono; private String Email; public int getID() { return mPersona.getID(); } public String getNombre() { return mPersona.getNombre(); } public String getApellido() { return mPersona.getApellido(); } public String getTelefono() { return Telefono; } public String getEmail() { return Email; } } class Cliente_VIP { private Cliente mCliente; private String NroCuenta; private Double LimiteCredito; public int getID() { return mCliente.getID(); } public String getNombre() { return mCliente.getNombre(); } public String getApellido() { return mCliente.getApellido(); } public String getTelefono() { return mCliente.getTelefono(); } public String getEmail() { return mCliente.getEmail(); } public String getNroCuenta() { return NroCuenta; } public Double getLimiteCredito() { return LimiteCredito; } }

Noviembre 19, 2008 9:49hs
Hola, muy interesante tu articulo. Que soft usas para los diagramas de clases? Espero tus proximas entradas sobre este tema. Muchas Gracias.
Noviembre 19, 2008 17:51hs
@Ivan: muchas gracias por el feedback. El soft que uso para los diagramas es Umbrello, (es para Linux). Pronto voy a publicar una sección con herramientas útiles como esta.
Saludos!
Enero 3, 2009 13:11hs
Excelente blog, he estado dando vueltas en los distintos artículos y me tuve que detener en alguno a dejar un comentario =)
Este patrón generalmente cae en desuso versus la herencia, debido a que generalmente es más fácil de realizar, es mejor su mantenimiento y a veces es hasta más legible (se entiende mejor que una clase herede de otra a que la decore).
Donde se usa Si o Si el patrón decorador siempre, es cuando uno encuentra una clase final (sealed, NotInheritable) que no le pertenece o que está en una librería compilada sin fuentes, y uno desea especializarla.
Si uno quisiera, por otra parte, simplificar o modificar de alguna forma la interfaz de esta clase se podría usar un patrón fachada (ese si lo uso de manera mas o menos regular).
Espero que continúes las actualizaciones, quedo pendiente.
Enero 3, 2009 15:14hs
@David Lay: Gracias por visitar y sobre todo por comentar, siempre es bueno ver un punto de vista diferente.