Decorator (patrón de diseño)

Transcripción

Decorator (patrón de diseño)
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
Decorator (patrón de diseño)
De Wikipedia, la enciclopedia libre
El patrón Decorator responde a la necesidad de añadir dinámicamente funcionalidad a un Objeto. Esto nos permite no tener que crear sucesivas clases que hereden
de la primera incorporando la nueva funcionalidad, sino otras que la implementan y se asocian a la primera.
Índice
1 Motivación
2 Aplicabilidad
3 Estructura
4 Participantes
5 Colaboraciones
6 Consecuencias
7 Implementación
7.1 Ejemplo C++
7.2 Ejemplo C#
7.3 Ejemplo Java
7.4 Ejemplo Python
7.5 Ejemplo de PHP
8 Enlaces externos
Motivación
Un ejemplo para poder ver la aplicabilidad del patrón decorador podría ser el siguiente:
Disponemos de una herramienta para crear interfaces gráficas, que permite añadir funcionalidades como bordes o barras de desplazamiento a cualquier
componente de la interfaz.
Una posible solución sería utilizar la herencia para extender las responsabilidades de la clase. Si optamos por esta solución, estaríamos haciendo un diseño
inflexible (estático), ya que el cliente no puede controlar cuando y como decorar el componente con esa propiedad.
La solución está en encapsular dentro de otro objeto, llamado Decorador, las nuevas responsabilidades. El decorador redirige las peticiones al componente y,
además, puede realizar acciones adicionales antes y después de la redirección. De este modo, se pueden añadir decoradores con cualidades añadidas
recursivamente.
En este diagrama de clases, podemos ver que la interfaz decorador implementa la interfaz del componente, redirigiendo todos los métodos al componente visual
que encapsula.
Las subclases decoradoras refinan los métodos del componente, añadiendo responsabilidades.
También se puede ver que el cliente no necesita hacer distinción entre los componentes visuales decorados y los sin decorar.
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
1/6
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
Aplicabilidad
Añadir objetos individuales de forma dinámica y transparente
Responsabilidades de un objeto pueden ser retiradas
Cuando la extensión mediante la herencia no es viable
Hay una necesidad de extender la funcionalidad de una clase, pero no hay razones para extenderlo a través de la herencia.
Existe la necesidad de extender dinámicamente la funcionalidad de un objeto y quizás quitar la funcionalidad extendida.
Estructura
Participantes
Componente
Define la interfaz para los objetos que pueden tener responsabilidades añadidas.
Componente Concreto
Define un objeto al cual se le pueden agregar responsabilidades adicionales.
Decorador
Mantiene una referencia al componente asociado. Implementa la interfaz de la superclase Componente delegando en el componente asociado.
Decorador Concreto
Añade responsabilidades al componente.
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
2/6
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
Colaboraciones
El decorador redirige las peticiones al componente asociado.
Opcionalmente puede realizar tareas adicionales antes y después de redirigir la petición.
Consecuencias
Más flexible que la herencia. Al utilizar este patrón, se pueden añadir y eliminar responsabilidades en tiempo de ejecución. Además, evita la utilización de la
herencia con muchas clases y también, en algunos casos, la herencia múltiple.
Evita la aparición de clases con muchas responsabilidades en las clases superiores de la jerarquía. Este patrón nos permite ir incorporando de manera
incremental responsabilidades.
Genera gran cantidad de objetos pequeños. El uso de decoradores da como resultado sistemas formados por muchos objetos pequeños y parecidos.
Puede haber problemas con la identidad de los objetos. Un decorador se comporta como un envoltorio transparente. Pero desde el punto de vista de la
identidad de objetos, estos no son idénticos, por lo tanto no deberíamos apoyarnos en la identidad cuando estamos usando decoradores.
Implementación
El patrón Decorator soluciona este problema de una manera mucho más sencilla y extensible.
Se crea a partir de Ventana la subclase abstracta VentanaDecorator y, heredando de ella, BordeDecorator y BotonDeAyudaDecorator. VentanaDecorator
encapsula el comportamiento de Ventana y utiliza composición recursiva para que sea posible añadir tantas "capas" de Decorators como se desee. Podemos crear
tantos Decorators como queramos heredando de VentanaDecorator.
Ejemplo C++
#include <iostream>
//[Clase Component] ver diagrama de clases
class IVentanaAbstracta
{
public:
};
virtual void Dibujar() = 0;
//[Clase ConcreteComponent] ver diagrama de clases, Clase que se desea decorar
class Ventana : public IVentanaAbstracta
{
public:
};
void Dibujar()
{
std::cout << " Ventana ";
}
//[Clase Decorator] ver diagrama de clases
class VentanaDecorator : public IVentanaAbstracta
{
public:
VentanaDecorator(IVentanaAbstracta* ventanaAbstracta)
{
_VentanaAbstracta = ventanaAbstracta;
}
virtual void Dibujar() = 0;
};
protected:
IVentanaAbstracta* _VentanaAbstracta;
//[Clase ConcreteDecorator] ver diagrama de clases
class BordeDecorator : public VentanaDecorator
{
public:
BordeDecorator(IVentanaAbstracta* ventanaAbstracta) : VentanaDecorator(ventanaAbstracta)
{
}
};
virtual void Dibujar()
{
std::cout << "|";
_VentanaAbstracta->Dibujar();
std::cout << "|";
}
//[Clase ConcreteDecorator] ver diagrama de clases
class BotonDeAyudaDecorator : public VentanaDecorator
{
public:
BotonDeAyudaDecorator(IVentanaAbstracta* ventanaAbstracta) : VentanaDecorator(ventanaAbstracta)
{
}
};
virtual void Dibujar()
{
_VentanaAbstracta->Dibujar();
std::cout << "[Boton de Ayuda]";
}
int main()
{
BotonDeAyudaDecorator* ventanaConBotonDeAyuda = new BotonDeAyudaDecorator(new Ventana());
ventanaConBotonDeAyuda->Dibujar();
std::cout << std::endl;
BordeDecorator* ventanaConBotonDeAyudaYBorde = new BordeDecorator(ventanaConBotonDeAyuda);
ventanaConBotonDeAyudaYBorde->Dibujar();
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
3/6
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
std::cout << std::endl;
BordeDecorator* ventanaConBorde = new BordeDecorator(new Ventana());
ventanaConBorde->Dibujar();
std::cout << std::endl;
BordeDecorator* ventanaConDobleBorde = new BordeDecorator(ventanaConBorde);
ventanaConDobleBorde->Dibujar();
std::cout << std::endl;
delete
delete
delete
delete
}
ventanaConBotonDeAyuda;
ventanaConBotonDeAyudaYBorde;
ventanaConBorde;
ventanaConDobleBorde;
return 0;
Ejemplo C#
using System;
using System.Collections.Generic;
using System.Text;
namespace Decorator
{
class Program
{
static void Main(string[] args)
{
BordeDecorator ventanaConBotonDeAyudaYBorde = new BordeDecorator(ventanaConBotonDeAyuda);
ventanaConBotonDeAyudaYBorde.Dibujar();
Console.WriteLine();
BordeDecorator ventanaConBorde = new BordeDecorator(new Ventana());
ventanaConBorde.Dibujar();
Console.WriteLine();
BordeDecorator ventanaConDobleBorde = new BordeDecorator(ventanaConBorde);
ventanaConDobleBorde.Dibujar();
Console.WriteLine();
}
}
Console.Read();
}
//[Clase Component] ver diagrama de clases
public interface IVentanaAbstracta
{
void Dibujar();
}
//[Clase ConcreteComponent] ver diagrama de clases, Clase que se desea decorar
public class Ventana : IVentanaAbstracta
{
public void Dibujar() { Console.Write(" Ventana "); }
}
//[Clase Decorator] ver diagrama de clases
public abstract class VentanaDecorator : IVentanaAbstracta
{
public VentanaDecorator(IVentanaAbstracta ventanaAbstracta) { _VentanaAbstracta = ventanaAbstracta; }
protected IVentanaAbstracta _VentanaAbstracta;
public abstract void Dibujar();
}
//[Clase ConcreteDecorator] ver diagrama de clases
public class BordeDecorator : VentanaDecorator
{
public BordeDecorator(IVentanaAbstracta ventanaAbstracta) : base(ventanaAbstracta) { }
public override void Dibujar() { Console.Write("|"); _VentanaAbstracta.Dibujar(); Console.Write("|"); }
}
//[Clase ConcreteDecorator] ver diagrama de clases
public class BotonDeAyudaDecorator : VentanaDecorator
{
public BotonDeAyudaDecorator(IVentanaAbstracta ventanaAbstracta) : base(ventanaAbstracta) { }
public override void Dibujar() { _VentanaAbstracta.Dibujar(); Console.Write("[Boton de Ayuda]"); }
}
Ejemplo Java
public abstract class Componente{
abstract public void operacion();
}
public class ComponenteConcreto extends Componente{
public void operacion(){
System.out.println("ComponenteConcreto.operacion()");
}
}
public abstract class Decorador extends Componente{
private Componente _componente;
public Decorador(Componente componente){
_componente = componente;
}
}
public void operacion(){
_componente.operacion();
}
public class DecoradorConcretoA extends Decorador{
private String _propiedadAñadida;
public DecoradorConcretoA(Componente componente){
super(componente);
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
4/6
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
}
}
public void operacion(){
super.operacion();
_propiedadAñadida = "Nueva propiedad";
System.out.println("DecoradorConcretoA.operacion()");
}
public class DecoradorConcretoB extends Decorador{
public DecoradorConcretoB(Componente componente){
super(componente);
}
public void operacion(){
super.operacion();
comportamientoAñadido();
System.out.println("DecoradorConcretoB.operacion()");
}
}
public void comportamientoAñadido(){
System.out.println("Comportamiento B añadido");
}
public class Cliente{
public static void main(String[] args){
ComponenteConcreto c = new ComponenteConcreto();
DecoradorConcretoA d1 = new DecoradorConcretoA(c);
DecoradorConcretoB d2 = new DecoradorConcretoB(d1);
d2.operacion();
}
}
Ejemplo Python
def establecer_costo_decorator(funcion):
def envoltorio1(instancia, costo):
funcion(instancia, costo)
return envoltorio1
def obtener_costo_decorator(costo_adicional):
def envoltorio1(funcion):
def envoltorio2(instancia):
return funcion(instancia) + costo_adicional
return envoltorio2
return envoltorio1
class Cafe(object):
@establecer_costo_decorator
def establecer_costo(self, costo):
self.costo = costo
@obtener_costo_decorator(0.5)
@obtener_costo_decorator(0.7)
@obtener_costo_decorator(0.2)
def obtener_costo(self):
return self.costo
cafe = Cafe()
cafe.establecer_costo(1.0)
print cafe.obtener_costo() # 2.4
Ejemplo de PHP
<?php
interface iCoffee
{
public function getBaseCost();
}
class Coffee implements iCoffee
{
protected $_baseCost = 0;
}
public function getBaseCost()
{
return $this->_baseCost;
}
class BlackCoffee extends Coffee
{
public function __construct()
{
$this->_baseCost = 5;
}
}
abstract class CoffeeDecorator implements iCoffee
{
protected $_coffee;
}
public function __construct(iCoffee $Coffee)
{
$this->_coffee = $Coffee;
}
class WithCream extends CoffeeDecorator
{
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 1.5;
}
}
class WithMilk extends CoffeeDecorator
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
5/6
20/10/2014
Decorator (patrón de diseño) - Wikipedia, la enciclopedia libre
{
}
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 4;
}
class WithChocolate extends CoffeeDecorator
{
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 5;
}
}
$coffee = new WithChocolate(new WithMilk(new WithCream(new BlackCoffee())));
echo 'El precio del cafe es: $' . $coffee->getBaseCost();
Enlaces externos
Patrón Decorator: explicación y modelo UML (http://design­patterns­with­uml.blogspot.com.ar/2013/02/decorator­pattern.html)
Patrón Decorator en PHP (http://desarrolladorsenior.blogspot.com/2009/09/patron­de­diseno­decorator­en­php5.html)
Obtenido de «http://es.wikipedia.org/w/index.php?title=Decorator_(patrón_de_diseño)&oldid=74104410»
Categoría: Patrones de diseño
Esta página fue modificada por última vez el 29 abr 2014 a las 19:31.
El texto está disponible bajo la Licencia Creative Commons Atribución Compartir Igual 3.0; podrían ser aplicables cláusulas adicionales. Léanse los términos de
uso para más información.
Wikipedia® es una marca registrada de la Fundación Wikimedia, Inc., una organización sin ánimo de lucro.
http://es.wikipedia.org/w/index.php?title=Decorator_(patr%C3%B3n_de_dise%C3%B1o)&printable=yes
6/6

Documentos relacionados