Nov 19

Patrón Decorador - Definición, diagramas e implementación

Etiquetas: Decorador, Java, Patrones Versión para imprimir Pablo

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;
	}
}

También te puede interesar:

Comentarios[4]

  1. IvanNo Gravatar

    Hola, muy interesante tu articulo. Que soft usas para los diagramas de clases? Espero tus proximas entradas sobre este tema. Muchas Gracias.

  2. PabloNo Gravatar

    @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!

  3. David LayNo Gravatar

    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.

  4. PabloNo Gravatar

    @David Lay: Gracias por visitar y sobre todo por comentar, siempre es bueno ver un punto de vista diferente.

Deja un comentario