PATRONES DE DISEÑO. Patrones estructurales (Structural patterns)
Patrones de Diseño (copia)
-
Upload
joan-manuel-zabala -
Category
Documents
-
view
14 -
download
0
Transcript of Patrones de Diseño (copia)
República Bolivariana de Venezuela
Ministerio de Poder popular para la Educación Universitaria
Universidad Politécnica Territorial del Oeste de Sucre “Clodosbaldo Russian”
Cumaná Estado Sucre
Patrones de Diseño de Software
“Decorator”
Cumaná, Junio de 2013
Introducción
El concepto de patrón software, más concretamente el concepto de patrón
de diseño, se hizo popular dentro del mundo del desarrollo del software en 1995
con la publicación del libro Design Patterns: Elements of Reusable Object-Oriented
Software, cuyos autores son Erich Gamma, Richard Helm, Ralph Jonhson y John
Vlissides (normalmente referenciados como la Banda de los Cuatro – The Gang of
Four – o simplemente por GoF).
Realmente el uso del término patrón, con el significado que actualmente se
le da en la Ingeniería del Software y más concretamente en el área de la
tecnología de objetos, se deriva de los trabajos del arquitecto Christopher
Alexander desde mediados de los años 60.
Existen varios tipos de patrones de diseño, entre los que destacan:
Adaptador, Factory, MVC, Registry, Decorator, entre otros. A continuación
explicaremos detalladamente el uso del patrón Decorator.
Contenido
Patrones de Diseño de Software
Según Brad Appleton 1997, un patrón es una unidad de información
instructiva con nombre que captura la estructura esencial y la comprensión de una
familia de soluciones exitosas probadas para un problema recurrente que ocurre
dentro de un cierto contexto y de un sistema de fuerzas.
Para James Coplien 1992, cada patrón es una regla constituida por tres
partes, la cual expresa una relación entre un cierto contexto, un cierto sistema de
fuerzas que ocurren repetidamente en ese contexto, y una cierta configuración de
software que permite a estas fuerzas resolverse así mismas.
Un patrón de diseño es una descripción de clases y objetos
comunicándose entre sí, adaptado para resolver un problema de diseño general en un
contexto particular. Se describen en forma textual, acompañados de diagramas
(habitualmente de clases e interacción) y pseudocódigo.
Cada patrón describe un problema que ocurre una y otra vez en nuestro
entorno y describe también el núcleo de l a so l uc i ón de p rob lemas , de
f o rma que pueda utilizarse un millón de veces sin tener que hacer dos
veces lo mismo.
Motivación e importancia en el uso de patrones
Los patrones de diseño son importantes de usar, porque sirven de guía
para resolver problemas comunes en programación. Al aprenderlos, aprenderás a
identificar de mejor manera los problemas que vas a tener, antes de que
aparezcan, y aprenderás qué solución es la que mejor se aplica a tu problema.
La idea de los patrones de diseño es especificar soluciones buenas y
determinar sus características de algún modo para que puedan ser integradas en
los diseños de aplicaciones incluso por diseñadores no expertos.
Clasificación
Según su propósito:
Patrones de creación. Se refieren a la creación de instancias.
Dentro de los patrones de creación tenemos:
o Abstract Factory . Proporciona una interfaz para crear familias de objetos
o que dependen entre sí, sin especificar sus clases concretas.
o Builder (Constructor). Separa la construcción de un objeto complejo de
su representación, de forma que el mismo proceso de construcción
pueda crear diferentes representaciones.
o Factory Method (Método de Fábrica). Define una interfaz para crear un
objeto, pero deja que sean las subclases quienes decidan qué clase
instanciar. Permite que una clase delegue en sus subclases la creación
de objetos.
o Prototype (Prototipo). Especifica los tipos de objetos a crear por medio
de una instancia prototípica, y crear nuevos objetos copiando este
prototipo.
Patrones estructurales. Se refieren a las relaciones entre clases y/u
objetos. Éstos son:
o Adapte r . Convierte la interfaz de una clase en otra distinta que es la que
esperan los clientes. Permiten que cooperen clases que de otra manera
no podrían por tener interfaces incompatibles.
o Bridge . Desvincula una abstracción de su implementación, de manera
que ambas puedan variar de forma independiente.
o Decorator . Añade dinámicamente nuevas responsabilidades a un objeto,
proporcionando una alternativa flexible a la herencia para extender la
funcionalidad.
o Facade . Proporciona una interfaz unificada para un conjunto de
interfaces de un subsistema. Define una interfaz de alto nivel que hace
que el subsistema es más fácil de usar.
o Flyweight . Usa el compartimiento para permitir un gran número de
objetos de grano fino de forma eficiente. Proxy. Proporciona un sustituto
o representante de otro objeto para controlar el acceso a éste.
o Composite . Permite combinar objetos en estructuras de árbol para
representar jerarquías. Permite además, agrupar varios objetos como si
fueran uno solo.
Patrones de comportamiento. Caracterizan la forma en que las clases u
objetos interactúan y distribuyen sus responsabilidades (servicios).
o Chain of Responsibility. Evita acoplar el emisor de una petición a su
receptor, al dar a más de un objeto la posibilidad de responder a la
petición. Crea una cadena con los objetos receptores y pasa la petición
a través de la cadena hasta que esta sea tratada por algún objeto.
o Command . Encapsula una petición en un objeto, permitiendo así
parametrizar a los clientes con distintas peticiones, encolar o llevar un
registro de las peticiones y poder deshacer la operaciones.
o Interpreter . Dado un lenguaje, define una representación de su
gramática junto con un intérprete que usa dicha representación para
interpretar las sentencias del lenguaje.
o Iterator . Proporciona un modo de acceder secuencialmente a los
elementos de un objeto agregado sin exponer su representación interna.
o Mediator . Define un objeto que encapsula cómo interactúan un conjunto
de objetos. Promueve un bajo acoplamiento al evitar que los objetos se
refieran unos a otros explícitamente, y permite variar la interacción entre
ellos de forma independiente. Memento. Representa y externaliza el
estado interno de un objeto sin violar la encapsulación, de forma que
éste puede volver a dicho estado más tarde.
o Observer . Define una dependencia de uno-a-muchos entre objetos, de
forma que cuando un objeto cambia de estado se notifica y actualizan
automáticamente todos los objetos.
o State . Permite que un objeto modifique su comportamiento cada vez que
cambia su estado interno. Parecerá que cambia la clase del objeto.
o Strategy . Define una familia de algoritmos, encapsula uno de ellos y los
hace intercambiables. Permite que un algoritmo varíe
independientemente de los clientes que lo usan.
o Template Method . Define en una operación el esqueleto de un algoritmo,
delegando en las subclases algunos de sus pasos. Permite que las
subclases redefinan ciertos pasos del algoritmo sin cambiar su
estructura.
o Visitor . Representa una operación sobre los elementos de una
estructura de objetos. Permite definir una nueva operación sin cambiar
las clases de los elementos sobre los que opera.
o Memento . Se utiliza para guardar el estado de un objeto y poder luego
restaurar el objeto a un estado previo.
o Proxy. Proporciona un representante o delegado que se encarga de
controlar el acceso a un objeto, generalmente por motivos de eficiencia.
Según su ámbito:
Patrones de clases. Tratan con relaciones de herencia (estática) entre
clases.
Patrones de objetos. Se refieren a relaciones de composición entre objetos,
que pueden cambiar en tiempo de ejecución y son más dinámicas.
Patrón Decorator
Este patrón de diseño permite añadir responsabilidades adicionales a un
objeto de forma dinámica. Proporciona una alternativa flexible a la subclasificación
para añadir funcionalidad, además, se usa cuando es imposible la extensión de
funcionalidad por herencia, por ser aquella imprevisible en tipo y número.
Aporta una mayor flexibilidad que la herencia estática, permitiendo, entre
otras cosas, añadir una funcionalidad dos o más veces. También evita concentrar
en lo alto de la jerarquía clases guiadas por las responsabilidades, es decir, que
pretenden (en vano) satisfacer todas las posibilidades. De esta forma las nuevas
funcionalidades se componen de piezas simples que se crean y se combinan con
facilidad, independientemente de los objetos cuyo comportamiento extienden.
Responde a la necesidad de agregar funcionalidad a un objeto por medio
de la asociación de clases. Es un objeto con el que se puede ejecutar
funcionalidades de varias clases a la vez.
Propósito del Patón Decorator
Permite añadir responsabilidades extra a objetos concretos de manera
dinámica
Proporciona una alternativa flexible a la herencia para extender
funcionalidad, también conocido como wrapper.
Implementación
Este patrón soluciona problemas 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.
El decorador debe cumplir la interfaz de la clase Componente para que el
cliente no distinga entre objetos básicos y decorados.
Cuando sólo exista la posibilidad de añadir un tipo de funcionalidad a los
objetos básicos se puede omitir la clase abstracta Decorador. En general
esto no es así y además conviene ponerla porque proporciona mayor
flexibilidad al diseño.
Se debe mantener la clase Componente o Component ligera. Así la
definición de los datos de representación debería hacerse en las subclases
porque si no se hará a las clases decoradoras muy pesadas para poder ser
usadas de forma anidada. Además añadir demasiada funcionalidad en la
interfaz Componente aumenta la probabilidad de que se pongan
características que para un caso en concreto no se utilicen.
Motivación
A veces se quiere añadir funcionalidad a un objeto concreto, no a una clase
entera.
Ej: Un toolkit para GUIs proporciona soporte para añadir marcos, barras de des-
plazamiento... a componentes.
Solución:
Herencia: no es flexible, la funcionalidad se añade estáticamente
Definir una clase “decoradora” que envuelve al componente, y le proporciona la
funcionalidad adicional requerida: más flexible, transparente al cliente, se pueden
anidar decoradores
Patrón de Diseño Estructural Decorator
Decorator es un patrón de diseño estructural, cuyo objetivo principal es el de
evitar un sin fin de clases herederas.
La idea de decorar un objeto (o envolver, como también se conoce), es
agregarle nuevas funcionalidades o características al mismo.
Estas nuevas funcionalidades se pueden lograr mediante el uso de herencia
simple, pero hay ocasiones en que la herencia genera muchas
combinaciones.
Con Decorator se quiere solucionar los siguientes problemas:
Se tiene un objeto al que se le quiere aplicar una nueva característica.
La característica se le debe aplicar dinámicamente.
No se sabe qué característica es la que se va aplicar.
Para lograr esto, se utiliza el siguiente patrón:
Hay algunos puntos a tomar en cuenta de este patrón de diseño:
Hay clases genéricas que van a ser heredadas, de manera que los métodos
del objeto a decorar sean accesibles.
Se crea un objeto “decorador” que conozca todas las características que se
van a agregar.
Se crean los objetos de características que las agregan.
Participantes
Component (VisualComponent): define la interfaz de los objetos a los que
se puede añadir responsabilidades de manera dinámica.
ConcreteComponent (TextView): define un objeto al que añadir responsa-
bilidades de manera dinámica.
Decorator: mantiene una referencia al objeto componente y define una in-
terfaz conforme a la del componente.
ConcreteDecorator (BorderDecorator, ScrollDecorator): añade responsabi-
lidades al componente al que referencia.
Colaboradores
El decorador redirige las peticiones al componente asociado y opcionalmente
puede realizar tareas adicionales antes o/y después de redirigir la petición.
Consecuencias
Es más flexible que la herencia estática.
Las responsabilidades se añaden y eliminan dinámicamente.
Facilita definir una propiedad varias veces (ej. doble marco).
Evita que las clases más altas en la jerarquía estén demasiado cargadas de
funcionalidad y sean complejas.
No hay precio que pagar por propiedades que no se usan.
Facilita la definición de nuevos decoradores.
Un decorador y el componente al que se refiere no son idénticos (esto es,
tienen distinto identificador).
Provoca la creación de muchos objetos pequeños parecidos y encadena-
dos, complicando la depuración.
Aplicabilidad
El patrón Decorator se usa:
Para añadir responsabilidades a objetos concretos de manera dinámica y
transparente, esto es, sin afectar a otros objetos
Para responsabilidades que se pueden añadir y quitar
Cuando la herencia sea impracticable, porque implique crear múltiples
subclases para todas las combinaciones posibles (ejm. TextViewScroll,
TextViewScrollBorder, ...)
Ejemplo del Patrón Decorator usando 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
{
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();
Diagrama de Clases del Patrón Decorator
Ventajas del Patrón Decorator
Amplía la funcionalidad de una interfaz al tiempo que la mantiene igual y se
hace dinámicamente.
No altera la funcionalidad existente, solo añade más funciones.
Las responsabilidades se pueden añadir o quitar.
Desventajas del Patrón Decorator
Si estas decorando demasiado a un objeto, vas a terminar con un montón
de decoraciones (clases) pequeñas. Si tu código está muy desordenado,
entonces vas a tener pesadillas tratando de encontrar las clases decorati-
vas.
Aumento en la complejidad a la hora de instanciar el objeto a ser decorado.
Al instanciarlo, debes envolverlo en quién sabe cuántas decoraciones, así
que es importante usar el sentido común.
El exceso de decoraciones que agregan métodos a un objeto, puede ser
problemático si no se especifican que decoraciones extienden el API del ob-
jeto y cuáles son los nuevos métodos que se aportan. Esta situación tam-
bién nos pueden causar dificultades cuando hay quedebuguear una aplica-
ción.
En algunos casos el programador debe aprender el orden en el cual las de-
coraciones deben ser instanciadas. Si vamos al último ejemplo, si el progra-
mador usa el decorador UpperCaseal final, los tags dentro del HTML van a
ser transformados a mayúsculas también. Por eso es vital que el programa-
dor entienda cuál es la intención detrás de cada decoración.
¿Es aplicable el patrón asignado para el diagrama de clase de su proyecto?
El patrón de diseño de software asignado (Decorator), no es aplicable al
diagrama de clases de nuestro proyecto, debido a que ninguna clase hereda de
otra clase.
Diagrama de Clase del Proyecto
Conclusiones
El patrón Decorator, nos permite extender objetos incluso en situaciones
cuando la extensión vía herencia no es viable o no es necesaria. Adicional-
mente nos ayuda a conservar el principio de Abierto/Cerrado, en donde se
dicta que cada entidad debe estar abierta a extensión pero cerrada a modi-
ficación.
Las decoraciones evitan la labor de crear clases complejas con mucho códi-
go, que en la mayoría de los casos no será evaluado. Se puede usar distin-
tas combinaciones (o secuencias) de decoraciones para generar distintos
comportamientos o resultados.
Para que una solución sea considerada un patrón debe poseer ciertas ca-
racterísticas. Una de ellas es que debe haber comprobado su efectividad
resolviendo problemas similares.
Bibliografía
http://kuainasi.ciens.ucv.ve/ideas07/documentos/tutoriales/
TUTORIALErnestoPimentel.pdf
http://es.scribd.com/doc/29568742/PATRONES-DE-DISENO-DE-SOFTWARE
http://zarza.usal.es/~fgarcia/doc/patrones1.pdf
http://www.ecured.cu/index.php/Patr%C3%B3n_de_dise%C3%B1o_de_software
http://es.scribd.com/doc/58071962/Informe-Patron-de-Diseno-Decorador-
Decorator
http://webdiis.unizar.es/~jmerse/IS-2/TeoriaPatronesV2_2.pdf