Post on 18-Jun-2020
Creado por: Javier Garzás
Actualizado por: Santiago Moral (santiago.moral@urjc.es)
Patrones de Diseño
Patrones, primer ejemplo
Javier Garzás, Introducción a los patrones de diseño
Primer ejemplo
Caso práctico: el (típico) videoclub
Se pretende diseñar el software referente a un videoclub.
Este software debe contemplar las películas, los clientes y
los alquileres que estos últimos realizan.
Existen dos tipos de películas, los estrenos y las regulares,
y el coste del alquiler varía en función de dichos tipos.
Javier Garzás, Introducción a los patrones de diseño
Primer ejemplo
PelículaCliente Alquiler*
*
1
1- titulo
+getCoste(diasAlquilada)
Diagrama de clases:
-diasAlquilada
Javier Garzás, Introducción a los patrones de diseño
Comienza la implementación
Realicemos el método getCoste() de la clase
Película:
Sabemos que dependiendo de la categoría de la
película (Estreno o Regular) se aplicarán tarifas
distintas.
¿Cómo podemos implementar esto?
…
Javier Garzás, Introducción a los patrones de diseño
Aparece la lógica condicional
public class Pelicula {
static final int REGULAR=0; static final int EXTRENO=1; private int categoria;
double getCoste(int diasAlquilada) {
double result = 0;
switch (getCategoria()) {
case REGULAR:
result += diasAlquilada*2; break;
case ESTRENO:
result += diasAlquilada*3; break;
}
return result;
}
int [getDiasTopeAlquiler | getCostePenalizaciónDia () | getDiasInhabilitacion | …]{
switch (getCategoria()) {
case REGULAR: …
case ESTRENO: …
}
…
Javier Garzás, Introducción a los patrones de diseño
La lógica condicional se propaga
public class Alquiler {
private int diasAlquilada; static final int 50PORCIENTO; static final int 75PORCIENTO;
int getDiasAlquiladaPromocion (int promocion)
switch (promocion) {
case 50PORCIENTO:
switch (Pelicula.getCategoria())
case REGULAR: …
case ESTRENO: …
case 75PORCIENTO:
…
}
}
Javier Garzás, Introducción a los patrones de diseño
La lógica condicional
Efectivamente, lo anterior funcionaría,
pero… ¿sería mantenible? :
A los dos meses de estar operativa la aplicación los
requisitos, como no, cambian, ahora aparece la
categoría “clásicos”, mañana “de los 80” y al otro
“en cartelera”…
En nuestra micro
aplicación tenemos
que tocar 5
métodos y dos
clases
Si nuestra aplicación
tuviese 80 clases, 12
constantes de
estado y 20 switch
repartidos por
distintas clases…
Javier Garzás, Introducción a los patrones de diseño
Bad Smells en la propuesta actual
Sentencias Switch
Existe una gran lógica condicional que depende del estado.
Frecuentemente, varias operaciones repetirán la misma
estructura condicional, al añadir más tipos tendremos que buscar
todos los switch.
Duplicación de código
La lógica condicional casi siempre produce duplicación de
código
Este es el peor bad smell, el anticristo de la mantenibilidad.
¡¿Solución?!
Javier Garzás, Introducción a los patrones de diseño
La esencia del problema
Película
- titulo
+getCoste(diasAlquilada)
PelículaEstrenoPelículaRegular
Problema: La clase película guarda dos roles
Solución:
Javier Garzás, Introducción a los patrones de diseño
¿Todo resuelto?
Más tarde observamos que una película debe
cambiar su categoría en run-time:
Tendremos, por ejemplo:
Objeto_PeliculaEstreno Objeto_PeliculaRegular
Solución: Podemos crear un nuevo objeto de la clase
PeliculaEstreno, sacar el estado del objeto de
PeliculaRegular, cargar todo en el objeto de Película estreno,
cambiar los apuntadores, matar el objeto de PeliculaRegular,
tener cuidado de que ningún otro objeto le apuntase, etc.
De todas formas, el objeto no cambiaría de clase,
tendríamos otro objeto de otra clase… OID único.
Javier Garzás, Introducción a los patrones de diseño
La esencia del problema
¡Un objeto nunca
puede cambiar
de clase!
Una película debe cambiar de categoría pero
un objeto no puede cambiar de clase
Tª: La relación de herencia es invariable en el tiempo
¿Cómo podemos solucionar este nuevo problema?
Javier Garzás, Introducción a los patrones de diseño
La solución final
Precio
+getCoste(diasAlquilada)
PrecioEstrenoPrecioRegular
Solución Final:
Pelicula
- titulo
+getCoste(diasAlquilada)
Javier Garzás, Introducción a los patrones de diseño
Ventajas
Nuevos estados y sus transiciones se añaden
fácilmente
Transiciones de estado explícitas
Estados localizados y con posibilidad de ser
compartidos
No hay switch
No hay código repetido
Etc.
Javier Garzás, Introducción a los patrones de diseño
¿Cuál era el primer problema?
Realmente, los requisitos presentaban
esencialmente este problema:
Los objetos de película cambian su comportamiento dependiendo
de su estado y dicho comportamiento debe cambiar en run-time.
Las operaciones que cambian no deben programarse con
múltiples sentencias condicionales porque hacen difícil el
mantenimiento.
Javier Garzás, Introducción a los patrones de diseño
Visión
¿Cuántas veces ha aparecido este problema?
¿A cuantos diseñadores le ha ocurrido?
¿No podríamos haber saltado del primer
diagrama de clases a la solución final?
¿Cuántas veces aparece código erróneo por qué
el diseñador no sabe o no tiene tiempo de
pensar la solución correcta?
¿Cómo aumentaría la calidad?
¿Se reduciría el tiempo?
Javier Garzás, Introducción a los patrones de diseño
Patrón State
Objetivo
Permite a un objeto alterar su comportamiento cuando su estado
interno cambia.
Motivación
Cuando un objeto cambia de estado puede responder de maneras
diferentes a los mismos mensajes.
La forma tradicional es poner sentencias condicionales.
Aplicabilidad
Un objeto cambia su comportamiento dependiendo de su estado y
dicho comportamiento debe cambiar en run-time. Las operaciones
que cambian se programan con múltiples sentencias condicionales
que hacen difícil el mantenimiento.
Javier Garzás, Introducción a los patrones de diseño
State
Estructura
La visión formal
Javier Garzás, Introducción a los patrones de diseño
El comienzo del movimiento
Christopher Alexander escribe varios libros
acerca del planeamiento urbano y la
construcción de edificios.
El origen formal del término patrón se atribuye a
él y a sus dos principales trabajos:
A Pattern Language (Alexander, 1977)
The timeless Way of Building (Alexander,
1979)
Javier Garzás, Introducción a los patrones de diseño
Patrones OO: Origen
1987. Ward Cunningham y Kent Beck aplican las
ideas de Christopher para desarrollar un
pequeño lenguaje de patrones, para aprender
Smalltalk: “Using Pattern Languages for Object-
Oriented Programs”
En 1990 se inicia el trabajo del “Gang of Four”
(GoF)
P. Coad, “Object-Oriented Patterns”, Comm.
ACM, Vol. 35, No 9, Sep. 1992, pp. 152-159.
Javier Garzás, Introducción a los patrones de diseño
Patrones OO: Madurez y Difusión
E. Gamma, R. Helm, R. Johnson and J. Vlissides,
“Design patterns: Elements of Reusable Object
Oriented Software”, Addison-Wesley, 1995.
F. Buschmann, R. Meunier, H. Rohnert, P.
Sommerlad and M. Stal, “A System of Patterns:
Pattern-Oriented Software Architecture”, Addison-
Wesley,1996.
Javier Garzás, Introducción a los patrones de diseño
Definición de patrón
“Una arquitectura reusable que la
experiencia ha mostrado que resuelve
un problema común en un contexto
específico”
Dictionary of Object Technology, 1995
Javier Garzás, Introducción a los patrones de diseño
Definición de patrón
“Cada patrón describe un problema que
ocurre una y otra vez en nuestro entorno,
describiendo el núcleo de la solución a
ese problema, de tal manera que esa
solución pueda ser usada más de un
millón de veces sin hacerlo dos veces de
la misma forma”
(Alexander, 1977).
Javier Garzás, Introducción a los patrones de diseño
Definición de patrón
Un patrón contempla, además de la solución a
un problema en un contexto:
Recurrencia
Enseñanza
Nombre
Consecuencias
Javier Garzás, Introducción a los patrones de diseño
Que no son los patrones
Invenciones, teoría o ideas no probadas
- ¿Teorías? No, no, son pura práctica
Soluciones que sólo han funcionado una vez
Cualquier cosa vieja escrita en formato de patrones
Principios abstractos o heurísticos
Aplicaciones universales para cualquier contexto
Una panacea (solución para cualquier mal)
Javier Garzás, Introducción a los patrones de diseño
¿Por qué usar patrones?
“Una cosa que los diseñadores expertos
no hacen es resolver cada problema
desde el principio [...]. Cuando
encuentran una buena solución la usan
una y otra vez. Esta experiencia es lo
que les hace expertos”
(Gamma ,1995)
Javier Garzás, Introducción a los patrones de diseño
¿Por qué usar patrones?
Diseño de
sistemas
escalables y
reutilizables es
complejo
Diseñar bien a
la primera vez
es imposible
El mercado
demanda
rapidez y
calidad
Usar soluciones
probadas
Aprovecharse de la
experiencia,
catalogarla y
documentarla.
Reutilizar
conocimiento
Componer un
vocabulario para
Ingenieros
Javier Garzás, Introducción a los patrones de diseño
Beneficios Potenciales
Mejora de la comunicación, el más potente.
¿Cómo podrían varios arquitectos discutir el diseño de un
edificio si sólo conocen la palabra ladrillo? La semántica
nos pierde.
Productividad y calidad, inmediatas cuando los
equipos puedan sostener discusiones de diseño
desde un alto nivel.
Javier Garzás, Introducción a los patrones de diseño
Clasificación de los patrones
Diferentes rangos de escala o niveles de
abstracción:
Patrones de Análisis
Patrones Arquitectónicos
Patrones de Diseño
Idioms
Patrones de Seguridad
Antipatterns (Ej. Copy and Paste Programming)
De dominios específicos
Patrones de Diseño
Javier Garzás, Introducción a los patrones de diseño
Patrones de Diseño
El objetivo que se pretende es conocer el principal catálogo sobre patrones de diseño:
“Design Patterns. Elementsof Reusable Object-OrientedSoftware”, by Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides
Ha sido reeditado 32 veces.
Javier Garzás, Introducción a los patrones de diseño
Patrones de Diseño
http://www.javacamp.org/designPattern
http://www.4shared.com/zip/c_uumpBU/The
_Design_Patterns_Java_Compa.html
Javier Garzás, Introducción a los patrones de diseño
Patrones de Diseño
Javier Garzás, Introducción a los patrones de diseño
Patrones de Diseño, los más destacados
Refinan un subsistema o componente de un sistema
software.
Describen una estructura a la cual muchas veces
recurrimos para resolver problemas de diseño.
No afectan a la arquitectura de un sistema
No dependen del lenguaje de implementación.
Permiten resolver problemas complejos y direccionan la
cooperación efectiva entre componentes
Javier Garzás, Introducción a los patrones de diseño
Descripción de un patrón (1/4)
Intención
Qué hace el patrón?
Cuál es su racionalidad e intención?
Qué problema de diseño ataca?
También conocido como
Otros nombres del patrón
Motivación
Un escenario que ilustra el problema y como la estructura
del patrón lo soluciona. El escenario ayuda a comprender la
descripción mas abstracta que sigue
Javier Garzás, Introducción a los patrones de diseño
Descripción de un patrón (2/4)
Aplicabilidad
En que situaciones es aplicable el patrón
Ejemplos de Diseños pobres solucionables con el patrón
Cómo reconocer estas situaciones
Estructura
Una representación gráfica de las clases en el patrón
Participantes
Descripción de la responsabilidad de los objetos y clases
participantes
Colaboraciones
Diagramas de colaboración entre los objetos y clases
participantes
Javier Garzás, Introducción a los patrones de diseño
Descripción de un patrón (3/4)
Consecuencias
Cómo logra el patrón sus objetivos?
Cuáles son los resultados de usarlo?
Qué partes de la estructura puede variar de manera
independiente?
Implementación
Qué técnicas utilizar para implementar el patrón?
Hay características específicas del lenguaje?
Javier Garzás, Introducción a los patrones de diseño
Descripción de un patrón (4/4)
Código de ejemplo
Fragmentos de código que ilustran como implementar el
patrón
Usos conocidos
Ejemplos de uso del patrón en sistemas reales
Patrones relacionados
Qué patrones están fuertemente relacionados?
Cuáles son las diferencias importantes?
Con qué otros patrones se debería usar éste?
Javier Garzás, Introducción a los patrones de diseño
Dimensiones de organización
Por propósito
Creacional
Estructura
Comportamiento
Ámbito
Clase
Objeto
Javier Garzás, Introducción a los patrones de diseño
Organización del catalogo
Creational Patterns
Abstraen el proceso de instanciación haciendo al
sistema independiente de cómo los objetos son
creados, compuestos o representados.
Alternativas de diseño por herencia o delegación.
Encapsulan el mecanismo de creación.
Independencia de los tipos de objetos “producto” que
manejemos.
Javier Garzás, Introducción a los patrones de diseño
Patrones de Creación (Gamma, 95)
Abstract Factory
Provee una interfaz para crear una familia de objetos relacionados sin especificar sus clases concretas
Factory Method
Define una interfaz para crear un objeto, dejando a las subclases decidir el tipo específico. Permite delegar la responsabilidad de instanciación a subclases
Singleton
Asegura una sola instancia de un objeto y provee un punto de acceso global a él
Builder
Separa la construcción de un objeto complejo de su representación, para que el mismo proceso de construcción permita crear varias representaciones
Prototype
Especifica el tipo de objetos a crear usando una instancia de creación (prototipo), y crea nuevas instancias copiando el prototipo
Javier Garzás, Introducción a los patrones de diseño
EJERCICIO
Precio
+getCoste(diasAlquilada)
PrecioEstrenoPrecioRegular
¿Qué tipo de patrón utilizarías para creación de
la clase Videoclub?
Pelicula
- titulo
+getCoste(diasAlquilada)
Javier Garzás, Introducción a los patrones de diseño
Patrón Singleton (1/4)
Javier Garzás, Introducción a los patrones de diseño
Patrón Singleton (2/4)
class SingletonException extends RuntimeException {
//new exception type for singleton classes
public SingletonException() {
super();
}
public SingletonException(String s) {
super(s);
}
}
Creamos una clase para lanzar una excepción…
Javier Garzás, Introducción a los patrones de diseño
Patrón Singleton (3/4)
class PrintSpooler {
//this is a prototype for a printer-spooler class
//such that only one instance can ever exist
static boolean
instance_flag=false; //true if 1 instance
public PrintSpooler() throws SingletonException {
if (instance_flag)
throw new SingletonException("Only one spooler allowed");
else {
Instance_flag = true; //set flag for 1 instance
System.out.println("spooler opened");
}
}
public void finalize() {
instance_flag = false; //clear if destroyed
}
}
Lanzamos la excepción…
Javier Garzás, Introducción a los patrones de diseño
Patrón Singleton (4/4)
public class singleSpooler {
static public void main(String argv[]) {
PrintSpooler pr1, pr2;
//open one spooler--this should always work
System.out.println("Opening one spooler");
try {
pr1 = new PrintSpooler();
} catch (SingletonException e) {
System.out.println(e.getMessage());
}
//try to open another spooler --should fail
System.out.println("Opening two spoolers");
try {
pr2 = new PrintSpooler();
} catch (SingletonException e) {
System.out.println(e.getMessage());
}
}
}
Creando una instancia de la clase…
Javier Garzás, Introducción a los patrones de diseño
Organización del catalogo
Structural Pattern
Determinan como combinar objetos y clases para
definir estructuras complejas.
Comunicar dos clases incompatibles,
Añadir funcionalidad a objetos
...
Javier Garzás, Introducción a los patrones de diseño
Patrones Estructurales (Gamma, 95)
Adapter
Convierte la interfaz de una clase en una interfaz que el cliente espera. Permite trabajar juntas a dos clases con interfaces incompatibles
Bridge
Desacopla una abstracción de su implementación y les permite variar independientemente
Composite
Compone objetos en jerarquías para representar relaciones parte-todo. Composite permite a los clientes tratar de la misma manera tanto a objetos individuales como a compuestos.
Decorator
Agrega dinámicamente nuevas responsabilidades a un objeto. Provee una alternativa muy flexible para agregar funcionalidad a una clase
Facade
Provee una interface única para un conjunto de interfaces en un sistema. Define una interface de más alto nivel que permite usar el sistema más fácil
Javier Garzás, Introducción a los patrones de diseño
Patrones Estructurales (Gamma, 95)
Flyweight
Soporta la representación de un gran número de objetos
pequeños de una manera eficiente.
Proxy
Provee un representante de acceso a otro objeto
Javier Garzás, Introducción a los patrones de diseño
Ejemplo de Aplicación
¿Problema?
Dibujo
Circulo
Cuadrado
Javier Garzás, Introducción a los patrones de diseño
Solución: Composite
Javier Garzás, Introducción a los patrones de diseño
Solución: Composite
Circulo Linea Grupo
Client
DibujoElementoDibujo
Javier Garzás, Introducción a los patrones de diseño
Organización del catalogo
Behavioral Patterns
Se ocupan de los algoritmos y reparto de
responsabilidades.
Describen los patrones de comunicación entre objetos y
clases.
Podremos definir abstracciones de algoritmos (Template
Method)
Cooperaciones entre objetos para realizar tareas
complejas, reduciendo las dependencias entre objetos
(Iterator, Observer, etc.)
Asociar comportamiento a objetos e invocar su ejecución
(Command, Strategy, etc.)
Javier Garzás, Introducción a los patrones de diseño
Comportamiento (Gamma, 95)
Chain of ResponsibilityEvita el acoplamiento entre el que envía y el que recibe una petición. Se encadenan los objetos que reciben las peticiones, el mensaje por la cadena hasta que alguno lo responda
CommandEncapsula una operación en un objeto, permitiendo parametrizaroperaciones, encolarlas, dejar log de ellas o deshacerlas
InterpreterDado un lenguaje, define una representación de su gramática que permita interpretar las sentencias del lenguaje
IteratorProvee una forma de tener acceso secuencial a los elementos de un conjunto sin exponer la implementación de éste último
Javier Garzás, Introducción a los patrones de diseño
Comportamiento (Gamma, 95)
MediatorDefine un objeto que encapsula la forma en la cual interactúan
otros. Promueve el acoplamiento débil
MementoSin violar el encapsulamiento, captura y externaliza el estado interno de un objeto, para que pueda ser recuperado más adelante
ObserverDefine una dependencia de uno a muchos de tal manera que cuando uno de ellos cambia, todos los que dependen de él son notificados y actualizados automáticamente
StatePermite a un objeto cambiar su comportamiento cuando su estado interno cambia. El objeto parecerá haber cambiado de clase
Javier Garzás, Introducción a los patrones de diseño
Comportamiento (Gamma, 95)
Strategy
Define una familia de algoritmos intercambiables y encapsulados.
Permite variar el algoritmo independientemente de quien lo usa
Template Method
Define un esqueleto de un algoritmo, delegando algunos pasos a
las subclases. Permite redefinir ciertos pedazos del algoritmo sin
cambiar su estructura
Visitor
Representa una operación que debe realizarse sobre los
elementos de una estructura de objetos. Permite definir nuevas
operaciones sin cambiar las clases de los objetos sobre las
cuales operan
Javier Garzás, Introducción a los patrones de diseño
Observer (1/5) Objetivo
Define una dependencia de uno a muchos entre objetos, de
manera que cuando un objeto cambia todos los que tienen
dependencia de él son informados.
Motivación
En casi todas las aplicaciones hay objetos que cuándo cambian
su valor deben de informar a otros objetos para que cambien su
estado en ese momento.
Aplicabilidad
Cuando una abstracción tiene diferentes aspectos y se desea
reutilizar algunos de ellos de forma separada. Cuando un
cambio en un objeto necesita realizar cambios en otros y no
se sabe a priori en cuantos objetos se hace este
cambio.Cuando un objeto debe notificar a otros de algún
cambio y no se desea que se acoplen entre ellos.
Javier Garzás, Introducción a los patrones de diseño
Observer (2/5)
Estructura
Javier Garzás, Introducción a los patrones de diseño
Javier Garzás, Introducción a los patrones de diseño
Observer (3/5)
Participantes
Subject: Conoce a sus observers, cualquier número de Observers
puede observar a un Subject. Define un interfaz para admitir
subscriptores.
Observer: Define un interfaz para los objetos que deben ser
notificados de los cambios en un Subject.
ConcreteSubject: Guarda los estados de interés de un
ConcreteObserver. Envía notificación a sus observers cuando su
estado cambia.
ConcreteObserver: Mantiene una referencia a un
ConcreteSubject. Implementa el interfaz Observer.
Javier Garzás, Introducción a los patrones de diseño
Observer (4/5)
Colaboraciones
Javier Garzás, Introducción a los patrones de diseño
Observer (5/5)
Consecuencias
Abstrae el acoplamiento entre Observer y Subject al definir un
interfaz estándar para todos ellos.
Soporta Broadcasting.
Debido a que la interfaz es estándar puede provocar llamadas de
actualización sobre Observers que no la necesitan.
Patrones relacionados
Mediator puede encapsular semánticas complejas de
actualización.
Singleton, al usar un Mediator puede ser importante que sea un
Singleton.
Javier Garzás, Introducción a los patrones de diseño
Una “clase” que no usa Observer
public class ControlDeTemperatura {
GUI InterfazUsuario;
public ControlDeTemperatura(InterfazUsuario
Interfaz){
InterfazUsuario=Interfaz;
}
public void receiveTemperatura (int temperatura,int
numSensor){
InterfazUsuario.nuevaTemperatura(temperatura,
numSensor);
}
}
Pudiéramos encontrar algo como:
Javier Garzás, Introducción a los patrones de diseño
Una clase que usa Observer.
Cuando debiéramos encontrar algo como:
public interface Observer {public void notify(float temperatura);}
public GUI implement Observer {public notify (float temperatura){...}
}
public class Subject {
Vector observers = new Vector();
public void addObserver(Observer observer){
observers.add(observer); }
public void removeObserver(Observer observer){
observers.remove(observer); }
public void notify(float valor){
for(int i=0; i<observers.size(); i++)
((Observer)observers.elementAt(i)).notify(valor)}
}
public class ControlDeTemperatura extend Subject
{ public void receiveTemperatura (int temperatura,int numSensor)}
Javier Garzás, Introducción a los patrones de diseño
CHAIN OF RESPONSIBILITY
Javier Garzás, Introducción a los patrones de diseño
Organizacion del catálogo
Abstract Factory
Builder
Prototype
Singleton
Adapter (Object)
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of
Responsibility
Command
Iterator
Mediator
memento
Observer
State
Strategy
Visitor
Factory Method Adapter (Class) Interpreter
Template Method
Creacional Estructural Comportamiento
Propósito
Clase
Objeto
Alcance
Javier Garzás, Introducción a los patrones de diseño
Ejemplo de Aplicación
¿Cómo organizar el control de la
aplicación y, además, agregar un
mecanismo para la creación de
macros?
Javier Garzás, Introducción a los patrones de diseño
Command