martes, 12 de febrero de 2013

Decorator Pattern

  • Clasificación del patrón: estructural.
  • Intención: extender la funcionalidad de un objeto en forma dinámica,  proporcionando una alternativa flexible a la creación de subclases.
  • También conocido como: Wrapper.
  • Aplicabilidad: Se utiliza este patrón cuando
    • se necesita añadir responsabilidades a objetos individuales dinámica y transparente, es decir, sin afectar a otros objetos.
    • se necesita retirar responsabilidades de algunos objetos.
    • la extensión por subclases es poco práctica. Por ejemplo, un gran número de extensiones independientes son posibles y produciría una explosión de subclases por cada combinación. También cuando la definición de clase puede estar oculta o no disponible para subclases.
  • Estructura:
  • Participantes
    • Component: define una interfaz para los objetos a externder en forma dinámica.
    • ConcreteComponent: define un objeto al cual se le puede extender con responsabilidades adicionales.
    • Decorator: mantiene una referencia a un objeto componente y define una interfaz que se ajusta a la interfaz de componente.
    • ConcreteDecorator: agrega responsabilidades al componente.
  • Colaboraciones
    • ConcreteDecorator-Component: el primero reenvía solicitudes a su objeto Component. Opcionalmente puede realizar operaciones adicionales antes y después de remitir la solicitud.
  • Implementación
    • La interfaz de un objeto decorador debe ajustarse a la interfaz del componente que decora (por herencia).
    • Omitiendo la clase Decorador abstracta. No hay necesidad de definir una clase Decorador abstracta cuando sólo tiene que añadir una responsabilidad.
    • Componentes livianos. Es importante mantener la clase Component liviana para evitar que los decoradores resulten demasiado cargados, es decir, debe centrarse en la definición de una interfaz, no en el almacenamiento de datos (quienes deberían ser tratados en subclases). Además, esta interfaz debe ser limitada, ya que si es amplia aumenta la probabilidad de que las subclases concretas terminen heredando funciones que no necesitan.
    • Decoratos vs Strategy: son dos formas alternativas de cambiar un objeto. El patrón Decorador sólo cambia un componente desde el exterior, de modo que los decoradores son transparentes para el componente. Con Strategy, el componente conoce las posibles extensiones, teniendo que hacer referencia y mantener las correspondientes estrategias.
  • Consecuencias
    • Ventajas
      • Mayor flexibilidad que la herencia estática. Con decoradores, las responsabilidades se pueden agregar y quitar en tiempo de ejecución con sólo conectar y desconectar ellos. Por el contrario, la herencia requiere la creación de una nueva clase para cada responsabilidad adicional.
      • Evita las clases cargadas de características, ya que permite la adición de responsabilidades. En lugar de tratar de soportar todas las características previsibles de una clase compleja y personalizable, se puede definir una clase simple y agregar funcionalidad incremental con objetos reenvía.
      • Son fáciles de personalizar por aquellos que entienden su estructura.
    • Desventajas
      • Un decorador y su componente no son idénticos. Un decorador actúa como una caja transparente, pero desde el punto de vista de la identidad del objeto un componente decorado no es idéntico a la del propio componente.
      • Un diseño que utiliza Decorator a menudo resulta en sistemas compuestos por gran cantidad de pequeños objetos parecidos. Los objetos sólo se diferencian en la manera en que están interconectados. Esto puede resultar difícil de aprender y depurar.
  • Motivación: A veces es necesario añadir responsabilidades a objetos individuales, no a una clase entera. Por ejemplo, cuando un conjunto de herramientas de interfaz gráfica de usuario debe permitir agregar propiedades a cualquier componente. Una forma de añadir responsabilidades es con la herencia, pero es poco flexible.
  • Ejemplo:
  • Patrones relacionados
    • Adapter: un Decorator sólo cambia las responsabilidades de un objeto, mientras que un adaptador dará a un objeto una interfaz nueva.
    • Composite: un Decorator puede ser visto como un composite de un solo componente. Sin embargo, un decorador añade responsabilidades adicionales.
    • Strategy: un Decorator permite cambiar la "piel" de un objeto, mientras que un Strategy le permite cambiar las "tripas" (por dentro).

No hay comentarios:

Publicar un comentario en la entrada