Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
TALLER DE PATRONES DE DISEÑO
Raquel Trillo Lado
Universidad de Zaragoza 2010
Patrones de diseño Máster en Bases de Datos e Internet
-2-
TABLA DE CONTENIDOS
Presentación de los patrones de diseño 3
Contextualización 3
Programación Estructurada VS Programación Orientada a Objetos (POO) 3
¿Por qué debemos conocer los patrones de diseño? 7
¿Qué es un patrón? 7
Consecuencias del uso de patrones de diseño 9
Clasificación de patrones de diseño 10
Objetivos del taller 11
Requisitos 11
Patrones Estructurales 12
El patrón Composite o Composición 12
El patrón Proxy 22
El patrón Decorator o Decorador 29
El patrón Facade o Fachada 39
El patrón Bridge o Puente* 43
El patrón Adapter o Adaptador* 45
El patrón Flyweight o Objeto Ligero* 49
Patrones de Creación 54
El patrón Prototype o Prototipo 54
El patrón Singleton o Instancia única* 58
El patrón Factory Method o Método de fabricación* 60
El patrón Abstract Factory o Fábrica abstracta* 63
El patrón Builder o Constructor* 65
Patrones de Comportamiento 68
El patrón Chain of Responsability o Cadena de Responsabilidad 68
El patrón State o Estado 73
El patrón Strategy o Estrategia 78
El patrón Observer u Observador 82
El patrón Iterator o Iterador* 89
El patrón Template Method o Plantilla* 92
El patrón Visitor o Visitante* 95
El patrón Command o Comando* 98
El patrón Memento o Recuerdo* 102
El patrón Mediator o Mediador* 104
Bibliografía y referencias 110
Patrones de diseño Máster en Bases de Datos e Internet
-3-
PRESENTACIÓN DE LOS PATRONES DE DISEÑO
Contextualización
• En general se han venido estudiando de forma separada Ingeniería del
Software y Diseño de Algoritmos y Programación.
• En Ingeniería del Software se suelen analizar los diferentes ciclos de vida de
construcción del software (cascada, espiral, prototipado, etc), metodología de
construcción, explotación y calidad del software (métrica, ISO 9000-3, etc.), y
modelos de objetos (OMT, UML, etc.).
• En Diseño de Algoritmos y Programación se suelen aprender las estructuras de
un lenguaje de programación y sus características y se implementan en ese
lenguaje problemas de diferente índole.
• Los Patrones de Diseño actúan como puente entre estas dos materias
(Ingeniería del Software y Diseño de Algoritmos y Programación). En palabras
de Donald Knuth, “First create a solution using sound software engineering
techniques, then if needed, introduce small violations of good software
engineering pinciples for efficiency’s sake”, es decir “Primero crear una
solución usando técnicas de ingeniería del software conocidas, luego si es
necesario, introducir pequeños camios de los principios de ingeniería del
software bien establecidos por razones de eficiencia”.
Programación Estructurada VS Programación Orientada a Objetos (POO)
• Programación Estructurada:
o Hace unos diez años que cayó en desuso pero todavía se sigue usando
sobre todo en aplicaciones legadas (legacy).
o Comprende fundamentalmente tres fases:
Análisis o captura de requisitos, donde de estudia el problema y
se definen las características que debe tener la solución.
Diseño, donde se construye el algoritmo que resuelve el
problema, ajustándose a las características que se han
especificado en la fase de análisis, basándose en los bloques
estructurales secuencia, condición e iteración. Por ejemplo
mediante la técnica diagramas de flujo.
Patrones de diseño Máster en Bases de Datos e Internet
-4-
Codificación o implementación, donde se traduce el diseño a un
lenguaje de programación estructurado como por ejemplo Ada,
Pascal, Cobol, Fortan,... En general esta traducción es bastante
directa.
o En general la mayoría de errores se introducen en la fase de diseño.
Además cuanto más tarde se detete un error más problemas suele
suponer. Debido a esto se dedica mucho tiempo a esta fase para tratar de
evitar errores tempranos.
o Supone que los requisitos permanecen inalterados durante todo el ciclo
de vida y que se conocen de antemano, de modo que cambios o nuevos
requisitos según Horowitz en 1993 suponen un 70% del coste total en
mantenimiento.
o Debido a esto se introdujo el ciclo de vida de desarrollo del software en
Espiral y el Prototipado en lugar de emplear el desarrollo en Cascada o
Cascada con realimentación.
Cascada y Cascada con realimentación: Fundamentalmente el
ciclo de vida del desarrollo del software se realiza en bloques.
Por lo tanto, en general, es necesario haber finalizado
completamente cada una de las fases antes de pasar a la siguiente.
Espiral y Prototipado. En general el ciclo de vida del desarrollo
del software es incremental de modo que se van aumentando
poco a poco las funcionalidades del sistema. En este tipo de
desarrollos existe gran interacción con el usuario con el fin de
disminuir los riesgos.
o Separación del modelo de datos (en general especificado mediante
diagramas Entidad-Relación o mediante ficheros) del modelo de
procesos (en general especificado mediante diagramas de flujo).
No se encapsulan las operaciones que se pueden realizar sobre los
datos.
Cambios en uno de ellos pueden provocar fallos en el otro porque
no se manejan de forma integrada.
• Programación Orientada a Objetos (POO):
Patrones de diseño Máster en Bases de Datos e Internet
-5-
o Hoy en día es la más usada aunque en ciertas áreas como por ejemplo,
implementación de algoritmos de cálculo numérico con gran carga de
operaciones, todavía se siguen empleando lenguajes estructurados como
Fortran.
o Se basa en la suposición de que los objetos del dominio de negocio en el
que se está trabajando son las entidades más estables del sistema de
modo que cualquier diseño basado en estos objetos será más resistente a
los cambios en las especificaciones que puedan darse posteriormente.
o Fusiona el/los modelos de datos y los modelos de proceso en clases de
objetos. Cada clase lleva incorporados los datos que requiere mediante
un conjunto de atributos que representan sus características y los
procesos necesarios para manipularlos mediante un conjunto de métodos
que representan su comportamiento. Además como ventaja adicional
reduce el vacío entre el software y los modelos de negocio, de modo que
un modelo de objetos o diagrama de interacción puede ser fácilmente
comprensible por un empresario.
o Las fases en el proceso de desarrollo del software son las mismas pero
los objetivos, métodos y técnicas de cada una de ellas difieren
enormemente:
Análisis o captura de requisitos: al igual que en el la
programación estructurada, en esta fase, se estudia el problema y
se definen las características (requisitos) que debe tener la
solución. La diferencia radica en que en este caso el análisis se
centra en el dominio de estudio y tiene como objetivo construir
un modelo del mundo real empleando objetos. Dicho modelo
suele expresarse mediante el modelo conceptual (diagrama de
clases que resuelve el problema pero no representa una
descripción de los componentes software) y diagramas de UML
como por ejemplo los casos de uso. (Fase de investigación)
Diseño, el objetivo de esta fase es crear es refinar los modelos
obtenidos en el análisis de modo que se enriquezcan con
suficientes detalles próximos a la implementación. Debido a esto
en esta fase es necesario comprobar que se cumplen los requisitos
Patrones de diseño Máster en Bases de Datos e Internet
-6-
y asignar responsabilidades e interacciones entre objetos. En esta
fase se suelen usar los diagramas de clases (extienden el modelo
conceptual de la fase de análisis enriqueciéndolo con atributos
métodos y relaciones de interacción), colaboración, estado y
ciclos de vida de UML. (Fase de búsqueda de solución lógica)
Codificación o implementación, al igual que en la programación
estructurada, en esta fase, se traduce el diseño elaborado a un
lenguaje de programación. El lenguaje seleccionado suele ser un
lenguaje orientado a objetos como por ejemplo Java, C++, C# o
cualquier otro de la familia .Net, SmallTalk, etc.; aunque podría
ser otro tipo de lenguaje, como por ejemplo un lenguaje
estructurado o un lenguaje funcional (Caml, Erlang, etc.).
o Problemas que se deben afrontar:
Se debe buscar un diseño reusable y suficientemente flexible a
cambios y ampliaciones (escable) a la vez que eficiente.
¿Cuáles son las clases y objetos que deben intervenir y qué
responsabilidad se le asigna a cada uno de ellos? ¿Cuál es la
granularidad correcta para las clases? ¿Cuándo usar la herencia
de clases y cuándo usar la implementación de una interfaz?
¿Cómo deben interactuar los objetos?, es decir, ¿cómo
intercambian mensajes (o peticiones, request) entre ellos para
realizar sus funciones (o responsabilidades)? o ¿Cuáles son las
relaciones entre ellos?
o En la metodología orientada a objetos sigue habiendo problemas
fundamentalmente por dos razones:
En algunos modelos de diseño existe un uso inadecuado de la
encapsulación de modo que hay una visibilidad de atributos y
métodos incorrecta. Esto suele provocar mayor acoplamiento
entre clases del debido, de modo que cambios en una de ellas
implica cambios en las demás, es decir mayor dificultad de
mantenimiento.
Patrones de diseño Máster en Bases de Datos e Internet
-7-
En muchos casos existe un vacío entre el análisis y el diseño y
entre el diseño y la implementación. Esto provoca que los
modelos proporcionados en la fase de diseño no sean buenos.
Fundamentalmente se dan dos problemas; o bien no se han
refinado suficientemente el modelo de modo que el
programador debe tomar decisiones de diseño sin tener
suficientes conocimientos del dominio; o bien existe una
sobreespecificación de modo que no se proporciona suficente
libertar al programador (p.e. especificándole una estructura de
datos concreta en donde implementar una lista).
¿Por qué debemos conocer los patrones de diseño?
• Los diseñadores expertos saben que no se debe empezar a resolver todos los
problemas desde el principio. Además también conocen diversas soluciones ya
probadas que le evitan “reinventar la rueda”. En general Los diseñadores senior
normalmente reusan soluciones que ya han trabajado anteriormente y que les
han proporcionado buenos resultados.
• 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. Es decir capturar la
experiencia para poder usarla eficientemente. Esta idea aplicada hoy al software
surgió de la arquitectura:
o Christopher Alexander “Each pattern describes a problem which occurs
over and over again in our environment, and then describes the core of
the solution to that problem, in such a way that you can use this solution
a million times over, without ever doing it the same way twice”.
o Christopher Alexander. A Pattern Language: Towns, Buildings,
Construction, 1977. The Timeless Way of Building, 1979.
¿Qué es un patrón de diseño?
• Víctor Gulías “Nuevo collar para un perro viejo: Abstracción”, es decir, dada
una solución a un problema específico se trata de determinar cuál es la esencia
de la solución eliminando la parte específica del contexto, de modo que dicha
Patrones de diseño Máster en Bases de Datos e Internet
-8-
esencia pueda ser usada para resolver problemas en contextos diferentes. De este
modo se permite el reuso de ideas (diseños) no sólo código.
• Definición 1: Es una solución de diseño válida en diferentes contextos y que ha
sido aplicada con éxito en el pasado(al menos una vez), la cual se cataloga de
modo que pueda ser aplicada en el futuro para resolver nuevos problemas con la
misma esencia. O lo que es lo mismo, es una solución de diseño a un problema
no trivial efectiva y reusable (se puede aplicar a un abanico de problemas de
diseño en distintas circunstancia).
• ¿Cómo se cataloga (describe) un patrón de diseño?
o Nombre del patrón: Describe un problema de diseño, su solución y las
consecuencias en una o dos palabras. En general se suele especificar en
castellano y en inglés.
o Clasificación (campo opcional): Indica de que tipo es el patrón.
o Propósito: Indica en dos o tres líneas cuál es el problema que intenta
resolver el patrón y su propósito.
o Otros nombres (Also Known As) (campo opcional): Si existen otros
nombres con los que es conocido en la comunidad deberían
especificarse.
o Motivación: Describe un ejemplo real de problema (el escenario) que ha
sido resuelto con el patrón, especificando la estructura que lo resuelve (la
solución). El escenario ayudará a entender la descripción más abstracta
que se indicará a continuación.
o Aplicabilidad: Especifica cuáles son las situaciones donde se puede
usar. Además da ejemplos de cómo puede solucionar problemas de
diseños pobres y cómo se pueden reconocer esas situaciones.
o Estructura: Especifica mediante notaciones gráficas (diagrama de
clases, colaboración y estado fundamentalmente) cuál es la solución al
problema de forma abstracta. Esta notación es sumamente importante
pero no es suficiente porque sólo captura el producto final del proceso de
diseño. Para poder reusar un patrón es necesario también recordar las
decisiones, alternativas y ventajas e inconvenientes a las que nos dirigen
además de ejemplos que nos puedan ayudar.
Patrones de diseño Máster en Bases de Datos e Internet
-9-
o Participantes: Lista las clases y objetos que intervienen en la estructura
del patrón y especifica cuál es la responsabilidad de cada uno de ellos.
o Colaboraciones entre participantes: Indica cómo interaccionan los
diferentes participantes (clases y objetos) que intervienen en su
estructura.
o Consecuencias: Describe las ventajas e inconvenientes de la aplicación
del patrón. Además se indica cómo soporta los objetivos y qué aspectos
del sistema pueden variar.
o Implementación: Técnicas y peligros que conlleva la implementación
del patrón.
o Código de ejemplo: Solución limitada que puede servir de base para
implementaciones que usen el patrón.
o Usos conocidos (campo opcional): Ejemplos de uso del patrón en
sistemas reales.
o Patrones relacionados (campo opcional): Listado de patrones
relacionados incidiendo en las diferencias de uso y en el posible uso
conjunto de estos, es decir con qué patrones debería usarse.
Consecuencias del uso de patrones de diseño
• Los patrones guardan experiencias de diseño orientado a objetos. Además
nombran, evalúan y explican diseños que se repiten a menudo en los sistemas
orientados a objetos.
• Facilitan el aprendizaje de diseñadores junior, y permiten ahorro de tiempo en la
elaboración de diseños puesto que la toma de decisiones es automática; debido a
que ayudan a escoger alternativas de diseño.
• Facilitan la comunicación entre diseñadores debido a que establecen un marco
de referencia de terminología y justificación, puesto que son conocidas las clases
que intervienen en ellos y las interacciones entre los objetos.
• Mejoran la documentación y el mantenimiento de las aplicaciones.
Clasificación de patrones de diseño
• Se realiza una clasificación en base a dos criterios:
Patrones de diseño Máster en Bases de Datos e Internet
-10-
o El propósito, el cual trata de reflejar lo que hace el patrón. Los patrones
pueden ser:
De creación: El próposito del patrón es crear nuevos objetos de
forma transparente al sistema.
Estructurales: Reflejan la composición formada por diferentes
objetos o clases con un objetivo establecido formando una
estructura mayor. Nos indican cómo estructurar en memoria los
objetos que intervienen en el problema.
De comportamiento: Reflejan la forma de interactuar diferentes
objetos o clases distribuyendo su responsabilidad para lograr un
objetivo establecido.
o El ámbito de aplicación, el cual trata de reflejar a que tipo de elementos
se aplica el patrón. Si se trata de relaciones entre clases estas pueden ser
establecidas en tiempo de compilación, mientras que si se trata de
relaciones entre objetos que pueden cambiarse de forma dinámica estas
tienen que ser establecidas en tiempo de ejecución.
Propósito Clasificación de los patrones de diseño
más conocidos Creación Estructural Comportamiento
Ámbito de
li ió
Clases Factory Method o Factoría
Adapter o Adaptador
Interpreter o Intérprete
Template Method o Plantilla
Patrones de diseño Máster en Bases de Datos e Internet
-11-
apliación
Objetos
Abstract Factory o Fábrica Abstracta
Builder o Puente
Prototype o Prototipo
Singleton o Instancia única
Adapter o Adaptador
Bridge o Puente
Composite o Composición
Decorator o Decorador
Facade o Fachada
Flyweight o Objeto ligero
Proxy
Chain of Responsability o Cadena de responsabilidad
Command o Comando
Iterator o Iterador
Mediator o Mediador
Memento o Recuerdo
Observer o Observador
State o Estado
Strategy o Estrategia
Visitor o Visitante
• Todos los patrones aquí enumerados han sido ampliamente probados y
empleados en diferentes sistemas. Además no pertenecen a ningún dominio
específico sino que resuelven problemas genéricos.
• Algunos de los patrones aquí descritos han sido incorporados como estructuras
de lenguajes del programación como por ejemplo el patrón observador en el
lenguaje SmallTalk o el patrón Iterador en el lenguaje Java.
Objetivos del taller
• Identificar las características fundamentales de los patrones más conocidos y
determinar cuándo se deben aplicar.
• Reproducir y modificar aplicaciones sencillas en las que se aplican patrones de
diseño codificados en lenguaje Java.
Requisitos
• Conocimientos previos: Orientación a objetos y UML.
• Software: Java 1.5.
Patrones de diseño Máster en Bases de Datos e Internet
-12-
PATRONES ESTRUCTURALES
Patrón Composite o Composición
• Clasificación: Estructural, debido a que nos indica cómo se organizan los
objetos en memoria para obtener una composición recursiva o lo que es lo
mismo una jerarquía en forma de árbol.
• Propósito: Construir una jerarquía compuesta por dos tipos de objetos:
primitivos (nodos hoja) y compuestos (nodos internos). Los objetos compuestos
permiten componer objetos primitivos y otros objetos compuestos en estructuras
arbitrariamente complejas. A este tipo de jerarquías también se le suele llamar
composiciones recursivas y jerarquías parte-todo.
El patrón permite a los clientes de los objetos composición tratar de forma
uniforme a los objetos primitivos y a las composiciones, es decir trata de igual
forma a los nodos hoja como a los árboles o nodos internos.
• Motivación: Diseño de un editor gráfico en dónde es posible construir objetos
complejos a partir de otros más simples. El cliente que usa esta jerarquía de
objetos complejos (en este caso el Editor) está interesado en tratar de forma
uniforme a los objetos primitivos y a los compuesto para simplificar su código.
o El método draw() en la clase Graphic es un método abstracto, por lo
tanto se declara su signatura pero no el código que lo implementa. De
este modo se obliga a tener una implementación de este método en cada
Patrones de diseño Máster en Bases de Datos e Internet
-13-
una de las subclases. Este método se emplea para tener una interfaz
común disponible para el editor de modo que pueda dibujar cualquier
objeto.
o La clase Graphic será una clase abstracta porque tiene al menos un
método abstracto.
o Para los demás métodos de la clase Graphic (los que realizan el
tratamiento de los hijos) se proporciona una implementación por defecto:
Implementación que no hace nada (se ignora)
Proporciona una excepción notificando que la operación no es
válida si se hace por un nodo hoja (puesto que estos la heredan y
no la redefinen)
Los componentes compuestos redefinen estas operaciones.
Estos métodos no pueden ser abstractos porque de ese modo los nodos
hoja no tendrían implementación de ellos (en cualquier caso no la tienen
que tener). Por otro lado es necesario poner estos métodos en la
superclase porque sino el Cliente tendría que conocer que existen dos
tipos de componentes (primitivos y compuestos).
o La flecha etiquetada con “graphics” representa la navegabilidad, es decir
el acceso va a ser siempre del objeto compuesto hacia los hijos de éste.
Depende del programador como se realice la implementación de esta
navegabilidad.
o Debido a que el rombo está pintado de negro (agregación en UML) es
responsabilidad de la clase Picture borrar todas las instancias hijas si esta
se elimina. Si se duda si el rombo debe estar rellenado o no mejor dejarlo
sin pintar.
o Las notas son sugerencias de cómo codificar los métodos cuando se
realice la programción del diseño.
• Aplicabilidad:
o Representar composición recursiva jerárquica, es decir jerarquías todo-
parte.
o Ignorar las diferencias en el tratamiento de objetos primitivos
(individuales) y objetos compuestos (composiciones)
Patrones de diseño Máster en Bases de Datos e Internet
-14-
• Estructura (Generalización del problema para aplicarlo a diferentes ámbitos):
• Participantes:
o Component o Componente (Graphic en el ejemplo motivador):
Representa el interfaz que se les presenta a los clientes y en
general se va a tratar de una clase abstracta.
Declara la interfaz común para los objetos de la composición (los
objetos hojas y los compuestos).
Declara la interfaz para regular la composición, es decir acceder y
manipular los componentes hijos. Se suelen dar al menos las tres
operaciones de este tipo que se mencionan en la estructura (añadir
componente, borrar componente y obtener hijo).
Implementa el comportamiento por defecto para los diferentes
componentes.
o Leaf o Hoja (Rectangle, Line, Text en el ejemplo motivador):
Representa un objeto primitivo, es decir un objeto hoja (sin
hijos).
Define el comportamiento de los objetos primitivos (básicos) de
la composición.
Patrones de diseño Máster en Bases de Datos e Internet
-15-
o Composite o Composición (Picture en el ejemplo motivador):
Representa un objeto compuesto, es decir el nodo raíz del árbol o
un nodo interno.
Define el comportamiento de los objetos compuestos, es decir de
los componentes con hijos. Este tipo de operaciones (operation())
en este tipo de clases en general se definen mediante delegación
en los componentes hijos. Es decir, en general las operaciones de
las hojas se definen aquí por delegación en los hijos.
Almacena los componentes hijos.
Implementa las operaciones relacionadas con los hijos de la
interfaz componente. Estas operaciones son las que van a regular
la asociación.
o Client o Cliente:
Maneja los objetos de la composición a través de la interfaz
común Componente, es decir sólo tiene conocimientos de la
superclase de la jerarquía de clases..
• Colaboraciones entre participantes:
o El cliente emplea la interfaz Componente (el API que actúa como
superclase) para interactuar con los objetos de la composición:
Si se actúa sobre una hoja, entonces la petición es realizada
directamente por la instancia correspondiente.
Si se actúa sobre una composición, en general s eredirige la
petición del compoenente a sus hijos y se realiza alguna acción
adicional (posiblemente antes o después de rediriguirle la
petición).
• Consecuencias (ventajas e inconvenientes):
o Ventaja 1: Simplifica el cliente debido a que trata a los objetos
compuestos y primitivos de forma uniforme. El cliente no conoce, ni
debería saber con lo que está tratando. Esto simplifica el código del
cliente porque evita tener que escribir funciones con sentencias
condicionales (if, case, selects, etc.) para las clases de la composición.
Patrones de diseño Máster en Bases de Datos e Internet
-16-
o Ventaja 2: Facilita la introducción de nuevos componentes sin afectar al
cliente.
o Desventaja: Resulta complejo restringir los componenetees de un objeto
compuesto, y para ello normalmente es necesario añadir comprobaciones
en tiempo de ejecución.
Por ejemplo: Imaginar que la figura compuesta tiene que estar
compuesta por un conjunto de figuras elementales todas del
mismo tipo. En este caso no es viable una comprobación en
tiempo de compilación y habría que llevarla a cabo en tiempo
de ejecución.
• Implementación: (Variantes del patrón y problemas que pudede desarrollar)
o Referencias explícitas al padre, es decir ¿qué pasa si a partir de los
hijos nos interesa llegar al padre?: Definir una interfaz para acceder al
padre de un componente en la estructura recursiva e implementarlo de la
forma apropiada. Varias posibilidades:
Obtener la navegación bidireccional en la relación children o
hijos. Por ejemplo si a partir de un fichero queremos saber cuál es
su directorio padre.si es que tiene alguno. Una opción sería poner
un atributo padre en la clase Fichero (Componente) y además
añadir ahí un método obtenerPadre() que nos devuelve un
Directorio. El padre necesitaría actualizarse en tiempo de
ejecución al hacerse llamadas al método addChild y
removeChild.
Esto tiene un efecto desagradable en el API y es que le damos al
cliente una referencia a la clase directorio y en principio el cliente
no debería saber que existen dos tipos de ficheros diferentes.
Establecer una relación recursiva de Fichero consigo mismo de
cardinalidad (0..1) de modo que se evite que el cliente tenga que
conocer la estructura de directorios. El problema aquí es que no
se está representando lo mismo y así un componente compuesto
podría ser hijo de un componente primitivo. Debido a esto
tenemos que reforzar el modelo para evitarlo. El refuerzo del
Patrones de diseño Máster en Bases de Datos e Internet
-17-
modelo se consigue mediante restricciones que tendrán que ser
comprobadas en tiempo de ejecución:
o En general el padre debe ser un objeto compuesto
(Directorio), para evitar que un nodo hoja (fichero
normal) sea el padre de otro nodo (fichero normal
o directorio).
o El padre de un objeto debe tener como uno de sus
hijos al objeto. La forma más sencilla de conseguir
esta restricción es cambiar sólo el padre de un
objeto cuando este siendo añadido o borrado a una
composición.
o Compartición de componentes: Cuándo se trabaja con objetos muy
pesado que no poseen estado puede interesarnos compartirlos de modo
que la representación incial en árbol deja de serlo porque se produce una
compartición de nodos. La representación de árbol pasa a ser la de un
grafo dirigido acíclico.
Por ejemplo si trabajamos con ficheros muy grandes y queremos
tenerlos accesibles desde diferentes puntos podremos crear
accesos directos a estos evitando duplicarlos.
En este caso hay que tener cuidado con la implementación de las
operaciones pues por ejemplo la operación de obtener tamaño tal
y como la habíamos planteado inicialmente aquí nos daría como
resultado para el directorio Raiz 1300 bytes y esto no es correcto.
Este tipo de implementaciones todavía se complicaría más si
quisiésemos tener la navegación en los dos niveles, es decir
guardar referencias a las listas de los padres.
o Maximizar la interfaz Component (Decisión que balancea
Seguridad-Transparencia): Uno de los objetivos del patrón
Patrones de diseño Máster en Bases de Datos e Internet
-18-
composición es que el cliente no sea consciente de qué objetos hojas y
compuestos se están usando. Para lograrlo la clase componente tiene que
definir tantas operaciones comunes para la composición y las hojas como
sea posible. En general la interfaz proporciona implementaciones por
defecto que se reescribirán en la subclase.
Este objetivo a veces entra en conflicto con el principio de diseño de la
jerarquía de clases que indica que una clase sólo debería definir
operaciones que son significativas a sus subclases, y en este caso hay
operaciones necesarias para los componentes que no tienen sentido para
las subclases. Además crea un conflicto de seguridad porque los clientes
pueden tratar de hacer operaciones poco significativas para las hojas.
¿Cómo puede la clase componente proporcionar una implementación por
defecto para ellas?
Es necesario ser creativos, por ejemplo, la interfaz para acceder a los
hijos es fundamental para los objetos compuestos pero no es necesaria
para los objetos hoja. Sin embargo si vemos la hoja como un
componenete que tienes hijos podemos definir una operación por defecto
para el acceso a los hijos en la superclase donde no se devuelve ningún
hijo. Las hojas usarán la implementación por defecto y la clase
compuesta la refinará.
o Declaración de métodos para la manipulación de los hijos: Se
proporciona una implementación por defecto:
Implementación que no hace nada (se ignora)
Proporciona una excepción notificando que la operación no es
válida si se hace por un nodo hoja (puesto que estos la heredan y
no la redefinen)
Los componentes compuestos en general redefinen estas
operaciones y los simples las heredan.
o Lista de Componentes en Component? En algunas ocasiones se
ingnora la clase Composite y se sustituye el modelado por:
Patrones de diseño Máster en Bases de Datos e Internet
-19-
Esto incurre en una penalización de espacio para todas las hojas, porque
tienen reservado el espacio para tener hijos aunque estas nunca lo usen.
Esta implementación es más sencilla (hay una clase menos) pero sólo
vale la pena si hay relativamente pocos nodo hoja en la estructura.
Si se usa esta implementación del patrón la asociación padre encaja con
mayor facilidad haciendo la asociación children bidireccional. Sin
embargo se corre el peligro de que se use el espacio de los hijos en los
nodo hoja para haer cualquier cosa.
o Ordenación de hijos: Puede diseñarse un orden de los hijos de un objeto
compuestos. Por ejemplo en el editor esto puede ser interesante para
reflejar la superposición de las figuras y en el ejemplo de los ficheros
para reflejar la antigüedad de los ficheros creados. Otro ejemplo en el
que podría resultar de utilidad es cuando la composición refleje árboles
sintácticos.
La ordenación en los hijos se logra mediante una restricción (ORDER)
en la asociación children o hijos. Esta restricción deberá tenerse en
cuenta a la hora de realizar la implementación.
o Mejora de rendimiento usando cachés en objeto Composición. En las
implementaciones del patrón es común usar una caché a nivel del objeto
compuesto que guarde información acerca de los hijos. Por ejemplo
cuando estamos tratando de obtener el tamaño de un directorio que
contiene otros directorios, si realizamos la operación tal y como la hemos
implementado se llama siempre a las operaciones de todos los
descendientes a pesar de que alguna parte de la estructura puede no
Patrones de diseño Máster en Bases de Datos e Internet
-20-
haberse modificado desde la última vez que se realizó la operación
obtener tamaño.
El uso de las cachés lleva asociado el problema de su actualización.
Cambios en los componentes hijos requeiren la invalidación de las
cachés de sus padres. De modo que este tipo de implementaciones
funcionará mejor cuando existen referencias a los padres.
o Responsabilidad de borrado. En general cuando no existe recolector de
basura lo más sencillo es hacer responsable del borrado de los hijos al
objeto compuesto que los contiene de modo que si se borra el objeto
compuesto este debe eliminar los hijos. Una excepción a esta regla se
produce cuando los objetos hijos pueden ser compartidos por varios
objetos compuestos. En Java, como tiene recolector de basura, si se
elimina un fichero de un objeto directorio simplemente bastará con
romper la asociación y el recolector de basura liberará la memoria
posteriormente del objeto eliminado de la asociación si este no está
referenciado por otro objeto compuesto sin tener que programar
mecanismos adicionales.
o Estructura de datos para almacenar hijos: En la fase de diseño no se
debe obligar a una estructura de datos concreta (listas enlazadas, arrays,
árboles, tablas hash, etc. ) esa elección deberá tomarse en la
implementación y dependerá de la eficiencia.
• Código de ejemplo y ejercicios:
o Ejercicio 1: Obtener una representación de los árboles de directorios y
los ficheros que estos contienen permitiéndonos conocer el tamaño que
ocupan en disco. Recordad que en muchos lenguajes los directorios se
tratan como ficheros. (Pista: Fichero, FicheroNormal y Directorio).
o Ejercicio 2: Implementar la clase Cliente. El cliente debe crear la
siguiente estructura de directorios:
Patrones de diseño Máster en Bases de Datos e Internet
-21-
A continuación se debe mostrar por pantalla el tamaño total del fichero raíz,
elimiar el directorio usr y elininar el fichero b. Finalmente se debe obtener de
nuevo por pantalla el tamaño del fichero (directorio) raíz.
o Ejercicio 3: Probar la clases anteriores y realizar un diagrama de
secuencia indicando como fluyen los mensajes entre los objetos. y hacer
un diagrama de secuencia indicando como fluyen los mensajes entre lso
diferentes objetos.
o Ejercicio 4: Aumentar el diseño anterior permitiendo la asociación padre.
o Ejercicio 5: Pensar en la estructura de un documento en un editor de
textos. Podría ser algo como lo que se indica a continuación:
o
Documento
Página
*
Columna
Línea Texto
Caracter
*
*
*
*
*Imagen
Frame
*
*
*
Patrones de diseño Máster en Bases de Datos e Internet
-22-
La tentación directa una vez hemos definido esto es implementar cada
una de las clases que aparece en el diagrama de forma independiente. Si
pensamos en mayor profundidad vemos que existe código muy parecido
entre por ejemplo los frames y las columnas y también entre los
caracteres y las imágenes.
Pensar como se podría realizar en diseño considerando el patrón
composición puesto que hay elementos que no pueden contener a otros
elementos del documento mientras otros si pueden..
• Patrones relacionados: Decorador, Iterador (realizar la navegación entre los
hijos), Objeto ligero (para compartir componentes), cadena de responsabilidad,
Visitante (localiza operaciones y comportamientos que deberían ser distribuidos
a lo largo de la composición y en las clases hojas).
Patrón Proxy
• Clasificación: Estructural, debido a que nos indica cómo se organizan los
objetos en memoria.
• Otros nombres: subrogado o subrogate.
• Propósito: Proporcionar un subrrogado o intermediario de un objeto para
controlar su acceso. El intermediario (o subrogado) controla el acceso al objeto
que estamos considerando.
• Motivación:
o Problema: En el contexto de un editor gráfico consideremos los objetos
gráficos (imágenes) que puede haber dentro de un documento.
En general no todas las imágenes van a tener que cargarse cuando
se abra el documento porque depende que zona estemos
visualizando hará que se muestren o no.
La apertura del documento debería ser rápida y en general las
imágenes suelen ser bastante pesadas, sobre todo si son de gran
tamaño.
o Solución: Debido a que no es necesario crear todos los objetos con
imágenes nada más abrir el documento porque no todas son visibles se
puede hacer carga bajo demanda.
Patrones de diseño Máster en Bases de Datos e Internet
-23-
La implementación de la carga bajo demanda por parte del editor
hace que este se complique, además la funcionalidad de carga
bajo demanda puede ser requerida por diversos módulos.
Modificar la clase imagen para que esta sepa cuando tiene que
cargarse en función de un estado interno tampoco parece una
buena opción porque esta clase se puede usar en otras
aplicaciones donde no se requiere la carga bajo demanda.
Crear una copia de la clase imagen y modificarla para permitir la
carga bajo demanda tampoco se considera un buen diseño porque
implica tener código duplicado con todas las desventajas que esto
conlleva.
Para evitar complicar el editor y dar al objeto imagen
responsabilidades que no le incumben (añadir funcionalidad
adicional a la clase imagen), se puede emplear un objeto proxy.
Este objeto se comportará como la imagen de cara al editor pero
será responsable de la carga bajo demanda de la imagen. En el
proxy se pude almacenar el nombre del fichero como una
referencia al objeto real (suponiendo que la imagen está en
disco).
El editor interactuará con el proxy, el cual delega en la imagen si
no puede resolver la operación por si mismo y se encarga de
realizar la carga bajo demanda.
Para que el editor no tenga conocimiento de la existencia de
proxies se crea una clase abstracta que propociona los métodos de
la imagen al editor, actuando como interfaz. Esta clase abstracta
actuará como superclase del objeto proxy y del real.
Patrones de diseño Máster en Bases de Datos e Internet
-24-
La clase ImageProxy cuando puede resolver las operaciones por
si misma las resuelve y proporciona el resultado (por ejemplo
devolver la extención o tamaño del fichero de la imagen), en caso
de que se le requiera una operación que implique la carga de la
imagen entonces la cargará en ese momento y delegará la
operación correpondiente en el objeto imagen.
• Aplicabilidad:
o Cuando exista una forma de referencia a un objeto más sofisticada que
un simple puntero, como por ejemplo las siguientes:
Proxy remoto: El proxy representa en local a un objeto remoto.
Este tipo de proxies es útil en aplicaciones distribuidas.
Proxy virtual: El proxy crea objetos costosos bajo demanda.
Proxy de protección: El proxy controla el acceso a un
determinado recurso (objeto original). Por ejemplo si disponemos
de una clase en concreto, denominémosla X, puede que esta no
realice la comprobación de los parámetros que llaman a sus
métodos. En muchas aplicaciones esta comprobación no será
necesaria pero en algunas otras puede ser requerido.
Patrones de diseño Máster en Bases de Datos e Internet
-25-
No se deberían incorporar las comprobaciones a la clase
porque esto la haría más pesada y en muchos casos no se
necesitarían (depende del cliente).
En lugar de la opción anterior el proxy puede realizar la
comprobación de los parámetros. Si los parámetros son
correctos el proxy delega la llamada en el objeto y sino
trata el problema.
Contar las veces que se accede a determinados métodos
para determinar cuales son las operaciones más
demandadas o tener uncontador de referencias al objeto
real para controlar la concurrencia al acceder a él.
• Estructura:
• Participantes:
o Proxy (ImageProxy):
Mantiene una referencia al objeto real (RealSubject). El proxy
puede referirse a Sujeto o Subject si las interfaces del Sujeto y
SujetoReal o RealSubject son las mismas.
Patrones de diseño Máster en Bases de Datos e Internet
-26-
Proporcioan la misma interfaz que el sujeto (Subject) para que un
proxy pueda ser substituido por el sujeto real.
Controla el acceso al objeto real y puede ser el responsable de su
creación y borrado, por ejemplo el proxy podría decidir liberar de
memoria un determinado objeto (en el ejemplo motivador la
Imagen) porque no se está usando en ese momento. Ojo con esto
porque puede ser que luego vuelvas a necesitar el objeto y la
creación del objeto también consume tiempo.
Además en función del tipo del proxy del que se trate:
Es el responsable de codificar una petición y sus
argumentos y enviarla al objeto remoto (Proxy Remoto)
disponible en una determinada dirección.
Actuá como caché de información del objeto real para
evitar en la medida de lo posible el acceso a este. (Proxy
Virtual o Caché).
Comprueba la corrección de los permisos y/o parámetros
de peticiones. (Proxy de protección).
o Subject (Graphic): Define la interfaz común del Proxy y el RealSubject
de modo que el proxy se pueda usar en cualquier lugar donde se espera
un sujeto real.
o RealSubject (Image): Define el objeto real que está siendo representado
por el proxy.
• Colaboraciones entre participantes: Dependiendo de la clase de proxy, el
objeto proxy realizará una serie de operaciones y redirigirá peticiones al objeto
real que está representando. Desde el punto de vista del cliente el proxy y el
sujeto real forman un objeto compuesto en donde el proxy envuelve al objeto
real.
• Consecuencias:
o Introduce un nivel de indirección en las peticiones que requieren acceder
al objeto, lo que conlleva a una pequeña penalización que en general
puede permitirse.
o Además dependiendo del tipo de Proxy:
Patrones de diseño Máster en Bases de Datos e Internet
-27-
Los proxies remotos ocultan el lugar donde residen los objetos
reales.
Los proxies virtuales realizan optimizaciones como por ejemplo
la carga bajo demanda o cacheado de resultados para evitar diferir
la operación al sujeto real.
Los proxies de protección permiten realizar diversas tareas ante el
acceso a un objeto como por ejemplo comprobar los parámetros o
permisos.
o Se pueden usar también en copias bajo demanda (copy-on-write o
creación bajo demanda), retrasando la replicación de un objeto hasta
que este cambia:
Crear una copia de un objeto complejo y de gran tamaño puede
ser una operación cara.
Además si la copia nunca se modifica no hay necesidad de
realizar ese gasto, usando un proxy se puede posponer el proceso
de copia hasta que sea requerido un cambio en la copia.
Para copiar bajo demanda es necesario que el objeto real
tenga un contador. La copia del objeto (solicitada a través
del proxy) no hará nada más que incrementar ese contador
de referencias. Solamente cuando se requiera un cambio
el proxy hace una copia y el contador se decrementa.
Además cuando la referencia es cero el sujeto real se
borra.
o Inicialmente la situación es esta:
o Cuando se solicita una copia la acción será crear
un nuevo proxy sobre el mismo sujeto real:
Patrones de diseño Máster en Bases de Datos e Internet
-28-
o Cuando se modifique alguna de las copias el proxy
solicitará la creación de la copia al objeto real.
o
Problemas de esto: Es necesario que el proxy sepa
que métodos modifican el estado del sujeto real y
también es necesario introducir un contador en el
sujeto real.
• Implementación:
o Los proxies no siempre necesitan conocer el tipo del sujeto real con el
que están trabajando. Si una clase proxy puede tratar con el sujeto real
sólo conociendo una interfaz abstracta entonces no hay necesidad de que
lo conozca y para instanciar el objeto real pueden emplear una factoría si
esta está disponible.
o Es necesario que los proxies tengan algún mecanismo para referenciar
cuál es el objeto real que les corresponde antes de instanciarlo.
• Patrones relacionados:
o Adaptador o Adapter: Un adaptador proporciona diferente interfaz al del
sujeto real (el objeto que adapta). En contraste un rpoxy proporciona la
misma interfaz que el sujeto real. Sin embargo un proxy usado para la
protección de acceso pudiera no logra una operación que el sujeto si
logra por lo tanto su funcionalidad puede ser efectivamente un
subconjunto de la funcionalidad del objeto real.
Patrones de diseño Máster en Bases de Datos e Internet
-29-
o Decorador o decorator: Aunque pueden tener implementaciones
similares a los proxies tiene diferente propósito. Un decorador añade más
responsabilidades al objeto en tiempo de ejecución mientras que un
proxy controla el acceso a él. En cualquier caso variantes del patrón
proxy son implementadas como decoradores como por ejemplo un proxy
de protección con varios niveles de control. Por otro lado los proxies
remotos y virtuales mantienen una referencia indirecta al sujeto real
(como por ejemplo la dirección del servicio o el nombre de la imagen) y
los decoradores mantienen una referencia directa.
• Código de ejemplo:
o Ejercicio1: Probar el código proporcionado que simula el
comportamiento del patrón y elaborar un diagrama de clases con su
estructura. ¿De qué tipo de proxy se trata y por qué?
o Ejercico 2: Realizar un diagrama de secuencia del código proporcionado.
Patrón Decorator o Decorador
• Clasificación: Estructural, debido a que nos indica cómo se establecen las
relaciones entre los diferentes elementos en memoria.
• Otros nombres: wrapper.
• Propósito: Añadir responsabilidades o características a un objeto en concreto
dinámicamente, proporcionando una alternativa flexible a la extensión de una
clase para aumentar la funcionalidad.
• Motivación:
o Problema: En el contexto de un editor de texto consideremos las
ventanas gráficas que muestran el documento.
Se desea que las ventanas donde se muestra el documento puedan
proporcionar un borde que estará activo cuando se esté trabajando
sobre esa ventana y una barra de desplazamiento o scroll si el
documento es de un tamaño considerable. Se desea añadir esa
responsabilidad a objetos en concreto no a una clase.
Además se pretende que estos dos funcionalidades adicionales no
supongan modificar el cliente, es decir que los clientes traten las
Patrones de diseño Máster en Bases de Datos e Internet
-30-
ventanas de la misma forma, posean las funcionalidades
adicionales o no por lo que no es viable modificar la clase
Ventana. La modificación de la clase Ventana supondría cargas
adecionales para otras aplicaciones que no requieren esas
funcionalidades.
o Solución 1: La alternativa más directa para modelar este problema es
usar la herencia para extender las responsabilidades de la clase Ventana y
crear una subclase VentanaConScroll, otra VentanaActiva y otra
ventanaActivaConScroll.
Esta solución es bastante ineficiente porque se produce una
explosión de clases a medida que se quieran proporcionar nuevas
funcionalidades.
Esta solución también es inflexible puesto que es estática y un
objeto es difícil que puede transformarse de una clase a otra
dinámicamente (en tiempo de ejecución); es decir, es una
sólución estática hecha en tiempo de compilación.
Esta solución provoca herencia múltiple que en determinados
lenguajes de programación puede ser difícil de implementar.
o Solución 2: Debido a los problemas que supone la creación de nuevas
subclases se opta por encapsular el objeto base (ventana o TextView)
dentro de otro objeto que añade las nuevas funcionalidades (objeto
decorador). Además como no se desea que el cliente diferencie entre
Patrones de diseño Máster en Bases de Datos e Internet
-31-
objetos sin decorar y decorados se considera una interfaz común
(visualComponent).
El decorador redirige las peticiones al objeto base y añade las
nuevas funcionalidades antes o después de la redirección.
Pueden existir diferentes tipos de funcionalidades que se desean
añadir (en el ejemplo motivador en concreto son dos: Scroll y
borde activo) por ello se considera una interfaz (Decorador) que
las engloba a todas y que actúa como mecanismo encapsulador.
Esta interfaz puede especializarse proporcionando el
comportamiento de las diferentes funcionalidades.
La superclase Decorator impelementa la interfaz del componente
visual, redirigiendo los métodos al componente que encapsula.
Además la transparencia de la interfaz VisualComponent permite
el anidamiento de decoradores permitiendo un número no
limitado de nuevas funcionalidades.
Las subclases decoradoras refinan los métodos del componente
añadiendo responsabilidades. Además las subclases pueden
Patrones de diseño Máster en Bases de Datos e Internet
-32-
añadir nuevas funcionalidades que no están disponibles en el
objeto sin decorar (scroolTo, drawBorder).
Los clientes de los componentes visuales no hacen distinción
entre los componentes decorados y sin decorar.
• Aplicabilidad:
o Añadir ó eliminar responsabilidades de objetos de forma dinámica y
transparente, sobre todo cuando no es práctico el uso de la herencia
debido a su inflexibilidad y explosión de clases.
• Estructura:
• Participantes:
o Componente o Component: Define la interfaz para que el cliente trate de
forma uniforme objetos decorados que objetos básicos.
o ComponeneteConreto o ConcreteComponent: Define un objeto al cual se
le pueden agregar responsabilidades adicionales.
o Decorador o Decorator: Mantiene una referencia al componente
encapsulado (asociado) e implementa la interfaz de la superclase
Componente. El Decorador delega en el componente asociado las
operaciones de la interfaz.
o DecoradorConcreto o ConcreteDecorator: Añade funcionalidades
(responsabilidades) al componente (refinamiento).
• Colaboraciones entre participantes:
Patrones de diseño Máster en Bases de Datos e Internet
-33-
o 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:
o Es una estructura más flexible que la herencia (la cual es estática) puesto
que es configurable en tiempo de ejecución y evita la herencia múltiple.
Además con el decorador las responsabiliddades pueden ser añadidas o
eliminadas y se evita la herencia múltiple.
o Evita la aparición de clases con muchas responsabilidades en las clases
superiores de la jerarquía permitiendo incorporar las responsabilidades
incrementalmente. Esto tiene la ventaja añadida de que no es necesario
pagar un coste por funcionalidades no requeridas. Además también es
sencillo definir nuevos tipos de decoradores independientemente de las
clases de objetos que extienden por ejemplo para extensiones no
previstas inicialmente.
o Puede provocar problemas con la identidad de los objetos. Un decorador
actúa como un envoltorio transparente de un objeto componente pero
desde el pundo de vista de la identidad de los objetos un componente
decorado no es idéntico al componente en si mismo puesto que no tienen
la misma referencia. Por lo tanto no se debería confiar en la identidad de
los objetos cuando usas decoradores.
¿Cuándo dos objetos son el mismo, cuando tienen la misma
referencia o cuamdno forman parte del mismo objeto compuesto,
el cual se construye sobre el mismo objeto base?
Se puede plantear una solución y usar un identificador calve
único (atributo id) para identificar los objetos de modo que no se
emplee la referencia. Nótese que el identificador sólo lo tendría el
objeto básico (TextView) y que los decoradores lo “heredarían”.
Es decir se pondría un atributo _clave en el TextView o en
Unidad y un método abstracto obtenerId(). El componente básico
devuelve el nomber en obtenerId() y los decoradores delegan en
el componente esa operación.
Patrones de diseño Máster en Bases de Datos e Internet
-34-
o Puede provocar la existencia de un gran número de objetos pequeños y
además se producen pequeñas penalizaciones por cada nivel de
indirección introducido.
• Implementación:
o El decorador debe cumplir la interfaz de la clase Componente para que el
cliente no distinga entre objetos básicos y decorados.
o 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.
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 sino 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.
o Patrón Decorador vs patrón Estrategia: En este caso se le están
añadiendo nuevas pieles (Decorador) que aumentan la funcionalida al
objeto base. Si en lugar de añadir funcionalidades se quisiese cambiar el
medio de conseguir la funcionalidad del objeto base entonces se
emplearía el patrón Estrategia. Además el patrón estrategia se debe
aplicar también cuando la clase Component es demasiado pesada.
En el patrón decorador el componente no tiene que saber nada de
los decoradores, es decir los decoradores son transparentes al
componente debido a que sólo se cambia un componente desde el
exterior.
En el patrón estrategia el componente en si mismo conoce sus
posibles extensiones. Además tiene referencias y mantiene las
correspondientes estrategias.
• Patrones relacionados:
Patrones de diseño Máster en Bases de Datos e Internet
-35-
o Adaptador: Un decorador es diferente de un adpatador en el sentido en
que el decorador sólo cambia las responsabilidades del objeto, no su
interfaz. Un adaptador proporciona una interfaz completamente nueva.
o Composición: Un decorador puede verse como una composición
degenerada con solo un componente (un hijo). Sin embargo un decorador
añade responsabilidades no es una agregación de objetos como lo es la
composición.
o Estrategia: El decorador cambia la piel del objeto y la estrategia su modo
de realizar las operaciones. Son dos alternativas diferentes de cambiar un
objeto.
• Código de ejemplo:
o Ejercicio 1: Crear un modelo e implementarlo para el siguiente
escenario. Se consideran Unidades (soldados) de un juego de estrategia.
Estas unidades pueden defender, atacar o moverse. Además tendrán un
método descripción que nos propocionará un String con la información
de las unidades (nombre y tipos de métodos que emplea). Las unidades
en un principio son SoldadosRaso (es decir capacidad de ataque, defensa
y movimiento 1) pero a medida que ganan experiencia pueden obtener
complementos (escudos y pistolas) que le ayuden a desarrollar su misión.
Por cada escudo que se adquiera la capacidad de defensa se multiplica
por dos y por cada pistola la capacidad de ataque se multiplica por 2
(Pista: Fichero, FicheroNormal y Directorio).
o Ejercicio 2: Implementa una clase Cliente de la estructura anterior que
poseea el siguiente método:
+ Unidad combate(Unidad atacante, Unidad defensor)
De modo que si la capacidad de ataque de la unidad atacante es
mayor que la capacidad de defensa de la unidad defensor,
entonces el ganador del combate es el atacante (return atacante),
en caso contrario el ganador del combate es el defensor (return
defensor).
o Ejercicio 3: Adapta el siguiente código para probar las clases anteriores:
Public class Main{
Patrones de diseño Máster en Bases de Datos e Internet
-36-
Public static void main (String argv[]){
Cliente c = new Cliente();
Unidad ryan = new Soldado (“Ryan”);
Unidad rambo = new Pistola( new Escudo(
new Soldado( “Rambo”)));
System.out.prinln(“Si ” +
Rambo.obtenerNombre() + “ataca a ” +
Ryan.obtenerNombre() + “, el vencedor es”
+ c.combate(rambo, ryan).obtenerNombre());
}
}
o Ejercicio 4: Si se desease disponer del método suprimirComplemento
¿dónde sería más adecuado hacerlo disponible?. Analizar las siguientes
opciones.
Opción 1: Nueva responsabilidad en la clase Complemento:
abstract class Complemento extends Unidad {
...
public Unidad suprime_complemento(Complemento
complemento) {
if (complemento == this)
return _sujeto;
else {
if (_sujeto instanceof Complemento)
_sujeto = ((Complemento) _sujeto)
.suprime_complemento(complemento);
return this;
}
}
...
}
Unidad p = new Escudo( new Soldado("mi_unidad") );
Patrones de diseño Máster en Bases de Datos e Internet
-37-
Unidad mi_unidad = new Pistola(p);
mi_unidad = ((Complemento) mi_unidad)
.suprime_complemento((Complemento) p);
Opción 2: Tratamiento uniforme de Unidades y Complementos:
abstract class Unidad {
...
public Unidad suprime_complemento(Unidad complemento) {
return this; }
...
}
abstract class Complemento extends Unidad {
...
public Unidad suprime_complemento(Unidad complemento) {
if (complemento == this)
return _sujeto;
else {
_sujeto =
_sujeto.suprime_complemento(complemento);
return this;
}
}
...
}
Unidad p = new Escudo( new Soldado("mi_unidad") );
Unidad mi_unidad = new Pistola(p);
mi_unidad = mi_unidad.suprime_complemento(p);
o Ejercicio 5: Si se desease pasar como parámetro un identificador del tipo
de complemento que se desea suprimir al método suprimirComplemento
¿cómo habría que modificar la implementación anterior?.
abstract class Unidad {
...
public Unidad suprime_complemento(String cual) { return this; }
Patrones de diseño Máster en Bases de Datos e Internet
-38-
...
}
abstract class Complemento extends Unidad {
...
protected abstract String tipo();
public Unidad suprime_complemento(String cual) {
if (tipo().equals(cual))
return _sujeto;
else {
_sujeto = _sujeto.suprime_complemento(cual);
return this;
}
...
}
class Escudo extends Complemento {
...
protected String tipo() { return "ESCUDO"; }
...
}
class Pistola extends Complemento {
...
protected String tipo() { return "PISTOLA"; }
...
}
Unidad mi_unidad = new Pistola(new Escudo(new
Soldado("mi_unidad")));
mi_unidad = mi_unidad.suprime_complemento("ESCUDO");
Nota: En ocasiones nos puede interesar tener identificado el
complemento que se manipula por ejemplo para borrarlo. Por
ejemplo si una Unidad dispone de dos pistolas igual nos interesa
Patrones de diseño Máster en Bases de Datos e Internet
-39-
eliminar la que adquirió en primer lugar y no una cualquiera de
ellas (como lo hace el método anterior.). En este caso en el
constructor del complemento será necesario indicar un
identificador.
Patrón Facade o Fachada
• Clasificación: Estructural.
• Propósito: Proporcionar una interfaz única para un conjunto de interfaces en un
subsistema. El objetivo es definir la interfaz de nivel más alto de las operaciones
que realiza el subsistema para que sea más sencillo el usarlo por otros módulos o
subsistemas diferentes, es decir facilitar el acceso.
• Motivación:
o En general la división de un sistema complejo en subsistemas facilita el
poder abordar el problema y reduce la complejidad.
o El objetivo que se persigue es minimizar las comunicaciones y puntos de
acceso de un subsistema a otro de modo que la dependencia entre
subsistemas se reduzca. Es decir, disminuir el acoplamiento entre
sistemas.
o Problema: En el contexto del desarrollo de un entorno de programación
integrado por ejemplo para el lenguaje C++; se desea disponer de una
herramienta debuger por lo que se requerirá hacer uso de un compilador.
o Solución 1: Conocer los diferentes módulos y componentes del
compilador (Scanner, Parser, etc.) de modo que pueda hacer llamadas a
cada uno de ellos.
Patrones de diseño Máster en Bases de Datos e Internet
-40-
o Solución 2: Usar el compilador como una caja negra de modo que los
cambios en la estructura del compilador o sus interfaces internas no
afecten, es decir no se propaguen más allá del punto de conexión que se
proporciona que será la fachada.
o Así se reducen las dependencias entre los módulos y se aisla a los
posibles clientes de los cambios internos del módulo. Sin embargo el
emplear una fachada no impide que existan aplicaciones especializadas
que puedan acceder a las clases del módulo directamente, es decir la
fachada no oculta las funcionalidades de más bajo nivel.
• Aplicabilidad:
Patrones de diseño Máster en Bases de Datos e Internet
-41-
o Necesidad de una interfaz más simple para un subsistema complejo
debido a que algunos clientes no necesitan conocer todo. Es decir a los
clientes sólo se le proporciona aquello que necesitan. La fachada
proporciona un punto de vista simple por defecto del subsistema y sólo
los clientes que necesiten mayor grado de personalización accederán
directamente al subsistema sin hacerlo mediante la fachada.
o Necesidad de reducir las dependencias entre las clases que implementan
un subsistema y sus clientes. Es decir, intentar acotar que un cambio en
el subsistema no se propague al exterior promoviendo la independencia
de los subsistemas y su portabilidad.
o Estructuración en capas de los subsistemas, de modo que cada fachada se
corresponde con un punto de entrada a cada nivel.
• Estructura:
• Participantes:
o Fachada o Facade (Compiler): Conoce las clases del subsistema
responsables de una determinada operación que se les está ofertando a
los clientes. Cuando un cliente le realiza una petición delega las
peticiones en los objetos apropiados del subsistema; es decir, las clases
realizan el proceso, la fachada no asume la responsabilidad.
o Clases del subsistema (Scanner, Parser, ProgramNode, etc.):
Implementan la funcionalidad del subsistema realizando el trabajo
solicitado por la Fachada. Estas clases no conocen la existencia de la
Fachada (no tienen referencias a la fachada).
Patrones de diseño Máster en Bases de Datos e Internet
-42-
• Colaboraciones entre participantes: Los clientes se comunican con el
subsistema enviando peticiones a la fachada, la cual redirige las peticiones a los
objetos apropiados. Aunque las clases del subsistema son las que realizan el
trabajo real, la fachada puede tener que realizar alguna operación por si misma
como por ejemplo traducir sus interfaces a las interfaces del subsystema
(delegación y adaptación de protocolos).
• Consecuencias:
o Reduce el acomplamiento entre clientes y subsistemas facilitando su uso
y aislando la implementación de modo que se pueden realizar cambios en
esta sin alterar el cliente. Además se reduce el número de objetos que el
cliente debe conocer.
o Los objetos del subsistema no conocen a la fachada por lo que es posible
tener diferentes fachadas que proporcionen acceso a diferentes tipos
(perfiles) de usuario.
o No impide que los clientes accedan a las clases del subsistema si resulta
necesario.
• Implementación:
o La reducción del acoplamiento entre clientes y subsistemas puede
reducirse incluso más si en lugar de emplear una fachada concreta la
fachada es una clase abstracta de la que se proporcionan diferentes
implementaciones del subsistema. Para instanciar una fachada en
concreto para un determinado cliente se debería usar una factoría.
• Patrones relacionados:
o Mediador o Mediator: Al igual que la fachada el mediador abstrae la
funcionalidad de clases existentes. Sin embargo, el propósito del
mediador es abstraer las comunicaciones arbitrarias que se producen
entre los objetos del subsistema centralizando a menudo una determinada
funcionalidad que no pertenece a ningún otro objeto del subsistema.
Además en el patrón mediador las clases del subsistema conocen a la
clase mediadora y realizan la comunicación con el mediador en lugar de
hacerlo unas con otras directamente. Por el contrario los objetos del
Patrones de diseño Máster en Bases de Datos e Internet
-43-
subsistema no tienen conocimiento de la fachada y esta no define nueva
funcionalidad.
o Instancia única o Singleton: En general sólo es necesario disponer de un
objeto fachada (si en la fachada no se almacena estado) por lo tanto se
suele usar este patrón en combinación con el patrón instancia única.
Patrón Bridge o Puente
• Clasificación: Estructural.
• Propósito: Desacoplar una abstracción de su implementación de forma que cada
una de ellas pueda variar independientemente.
• Motivación:
o En general para realizar la implementación de abstracciones se suele
emplear la herencia. El problema que genera la herencia es que asocia de
forma permanente la implementación y la abstracción.
o Problema: En un entorno de ventanas que puede funcionar en dos
sistemas de ventanas diferentes (por ejemplo Windows y Mac), la
abstracción “Ventana” permite desarrollar aplicaciones que funcionen en
los dos sistemas pero la implementación de esta abstracción deberá ser
distinta en uno que en otro.
o Solución 1: La solución directa sería implementar la clase abstracta
“Ventana” con subclases que implementen la abstracción en cada
entorno. Esta solución genera los siguientes problemas:
Es complejo poder extender la abstracción porque implica
modificar cada una de las subclases.
Existen problemas de dependencia de la plataforma.
Patrones de diseño Máster en Bases de Datos e Internet
-44-
o Solución 2: Separar en jerarquías diferentes la abstracción de la ventana
y sus implementaciones dependientes de la plataforma.
o De este modo todas las operaciones utilizadas en las subclases de
Windows se definen como métodos abstractos de la Interfaz WindowImp
(puente o brige).
• Aplicabilidad:
o Desacoplar abstracciones de sus implementaciones permitiendo el
cambio en tiempo de ejecución.
o Necesidad de extender mediante herencia tanto la abstracción como sus
implementaciones.
o El cambio en la implementación de una abstracción no debería afectar a
los clientes.
o Necesidad de compartir una misma implementación.
• Estructura:
Patrones de diseño Máster en Bases de Datos e Internet
-45-
• Participantes:
o Abstracción (Abstraction): Define la interfaz de la abstracción y
mantiene la referencia al objeto implementador.
o Abstracción refinada (RefinedAbstraction): Extiende la interfaz definida
por la abstracción.
o Implementador (Implementor): Define la interfaz para los
implementadores concretos. Esta interfaz no tiene porque corresponderse
con la interfaz de la abstracción (Implementador->primitivas,
Abstracción->operaciones de alto nivel).
o Implementador concreto (ConcreteImplementorX)
• Colaboraciones entre participantes:
o La abstracción redirige peticiones del cliente al objeto implementador.
• Consecuencias:
o Desacoplamiento entre interfaz e implementación.
Elimina dependencias de compilación.
Posibilidad de configuración en tiempo de ejecución.
o Facilita el poder extender independientemente las jerarquías de
abstracción e implementación.
o Oculta los detalles de implementación a los clientes.
• Implementación:
o Único implementador.
o Creación del objeto implementador.
Patrones de diseño Máster en Bases de Datos e Internet
-46-
Si la abstracción conoce la jerarquía de implementadores
entonces puede crear el implementador en el constructor en base
a sus parámetros.
Si la abstracción no conoce la jerarquía de implementadores
entonces deberá delegar en otro objeto que se encargue de
proporcionarle el implementador concreto, por ejemplo una
Factoría.
o Compartición de implementadores.
o Herencia múltiple.
Patrón Adapter o Adaptador
• Clasificación: Estructural.
• Propósito: El adaptador o wrapper permite la colaboración entre clases con
interfaces incompatibles.
• Motivación:
o Reutilizar clases con interfaces incompatibles.
o Problema: En el contexto de un editor gráfico se manipulan objetos que
cumplen una determinada interfaz (Shape). Esta interfaz abstrae a:
Clases elementales como por ejemplo líneas y polígonos
sencillos.
Clases relativas a la edición de texto no básica.
Además se pretende reutilizar la clase existente de otra librería
(TextView), pero inicialmente esta librería no fue diseñada teniendo en
cuenta la interfaz Shape.
o Solución 1: Modificar la clase TextView para que cumpla la interfaz
Shape. Esta solución en general es inaceptable porque esto puede
implicar alterar otras aplicaciones en funcionamiento o duplicar código.
o Solución 2: Emplear un adaptador.
Patrones de diseño Máster en Bases de Datos e Internet
-47-
• Aplicabilidad:
o Se desea emplear una clase existente que no es compatible con el interfaz
que se le requiere.
o Se desea crear una clase reusable que coopere con clases no relacionadas.
o Se desea usar diversas subclases existentes pero resulta impráctico
adaptar sus interfaces mediante la extensión de todas ellas por lo que se
emplea un objeto adaptador de la clase padre.
• Estructura:
o Opción 1 (herencia): La clase adaptadora implementa los métodos de la
interfaz pública deseada (Target) e implementa la clase que se desea
adaptar (heredando su métodos).
o Opción 2 (composición): La clase adaptadora implementa los métodos de
la interfaz pública deseada (Target) y usa un objeto de la clase que se
desea adaptar para delegar parte del trabajo.
Patrones de diseño Máster en Bases de Datos e Internet
-48-
• Participantes:
o Objetivo o Target: Define la interfaz dependiente del dominio usada por
el cliente.
o Cliente o Client: Colabora con los objetos de acuerdo con el interfaz
Objetivo o Target.
o Adaptado o Adaptee: Define una interfaz existente que necesita ser
adaptada.
o Adaptador oAdapter: Adapta la interfaz del adaptado a la interfaz
Objetivo.
• Colaboraciones entre participantes: El cliente envía mensajes al adaptador y
éste en repuesta los envía al objeto adaptado.
• Consecuencias:
o En ocasiones, permite la incorporación de funcionalidades no disponibles
en la clase adaptada.
o Clase adaptadora:
No permite adaptar una clase y todas sus subclases.
Si se opta por la opción 1 no existe indirección.
La clase adaptadora permite redefinir parte del comportamiento
del adaptado.
o Objeto adaptador:
Un adaptador permite adaptar a diversos objetos que poseen un
antecesor común.
Patrones de diseño Máster en Bases de Datos e Internet
-49-
Difícil cambiar el comportamiento del adaptado. Para ello sería
necesario extender el objeto adaptado y adaptar la nueva
subclase.
Patrón Flyweight o Objeto Ligero
• Clasificación: Estructural.
• Propósito: Uso compartido de un gran número de objetos lígeros (o de grano
fíno) para aumentar la eficiencia.
• Motivación:
o Problema: En el contexto de un editor de documentos se emplean
objetos para representar sus elementos: tablas, figuras, caracteres, etc.
Además se desea tratar a los elementos de forma uniforme. El problema
es que mantener un objeto para cada letra por ejemplo puede ser muy
caro.
o Solución 1: Tratar los caracteres de forma especial, es decir dar un
tratamiento específico para los caracteres en los diferentes algoritmos.
o Solución 2: Compartir objetos que pueden usarse al mismo tiempo en
diferentes contextos. A estos objetos los denominaremos objetos ligeros
o flyweight.
Patrones de diseño Máster en Bases de Datos e Internet
-50-
El objeto ligero o flyweight actúa como un objeto independiente
que no se diferencia del objeto compartido.
Distinción en el estado del objeto ligero (por ejemplo el formato
de la letra o el carácter que se representa):
Estado intrínsico: El estado se almacena dentro del objeto
ligero e independientemente del contexto en el que se usa.
(La letra que se representa)
Estado extrínsico: El estado depende del contexto en el
que se encuentra el objeto de modo que el objeto ligero no
puede ser compartido. (La posición y el formato o el estilo
que se le da al caracter).
Los clientes del objeto ligero son los responsables de
proporcionar el estado extrínseco al objeto ligero cuando lo
necesite.
Patrones de diseño Máster en Bases de Datos e Internet
-51-
• Aplicabilidad:
o Si se desea compartir objetos y se cumplen las siguientes condiciones:
Existe un gran número de los objetos que se desean compartir.
El coste de almacenamiento es alto debido a la gran cantidad de
objetos que se requieren.
La mayor parte del estado puede hacerse extrínsico.
Muchos grupos de objetos pueden reemplazarse por
relativamente pocos objetos compartidos al eliminar el estado
extrínsico.
No se depende de la identidad entre objetos.
• Estructura:
Patrones de diseño Máster en Bases de Datos e Internet
-52-
• Participantes:
o ObjetoLigero o Flyweight: Declara la interfaz mediante la cual los
objetos ligeros reciben y actúan sobre el estado extrínseco.
o ObjetoLigeroConcreto o ConcreteFlyweight: Implementa la interfaz del
objeto ligero añadiendo el estado intrínseco.
o ObjetoLigeroNoCompartido o UnsharedConcreteFlyweight: Puede hacer
objetos con la interfaz de objeto ligero que no se compartan. En general
estos objetos contienen a otros objetos ligeros (fila, columna, etc.).
o FábricaDeObjetosLigeros o FlyweightFactory: Crea y gestiona los
objetos ligerso y asegura la correcta compartición de los objetos ligeros.
o Cliente o Client: Mantiene referencias a objetos ligeros y calcula (o
almacena) el estdo extrínsico de los objetos ligeros.
• Colaboraciones entre participantes:
o El estado extrínsico es almacenado o calculado por lo clientes y
proporcionado a los objetos ligeros cuando estos lo necesitan.
o Los clientes no instancian directamente los objetos ligeros, sino que
delegan esta responsabilidad en la fábrica de objetos ligeros para la
correcta gestión de la compartición de estos.
• Consecuencias:
o Penalización en el cálculo del estado extrínseco.
o Reducción en los costes de almacenamiento, puesto que se reduce el
número total de instancias y se almacena un solo estado intrínseco por
objeto.
• Implementación:
Patrones de diseño Máster en Bases de Datos e Internet
-53-
o Eliminar el estado extrínsico.
o Gestión de los objetos compartidos.
o Combinación con el patrón Composición o Composite para construir
grafos dirigidos acíclicos.
Los objetos ligeros no pueden tener un enlace al padre porque
dependen del contexto (estado extrínseco).
Patrones de diseño Máster en Bases de Datos e Internet
-54-
PATRONES DE CREACIÓN
Patrón Prototype o Prototipo
• Clasificación: Patrón de creación porque de forma transparente (sin necesidad
de conecer la estructura de las instancias) crea objetos.
• Propósito: Especificar la clase de objetos a crear mediante la clonación de un
prototipo u objeto ya instanciado.
• Motivación:
o En el contexto de la construcción de un editor gráfico que se plantea en
el inicio del curso. Entre otras opciones, existen unas herramientas
(GraphicTool) que permiten crear objetos nuevos (rectángulo, círculos,
…). Los objetos creados pertenecen a una jerarquía de objetos (Graphic
o Figura) cuyas clases derivadas son particulares para la aplicación.
o Además de la jerarquía de objetos Graphic o figura existe una jerarquía
de herramientas (Tool) que debería ser aplicable en otras aplicaciones
como por ejemplo Mover, Rotar, Crear objetos nuevos, etc. Nótese que
podría existir una fachada que nos proporcionase las operaciones de
mover, rotar etc. y nos ocultase la jerarquía de herramientas.
o Problema 1: Las herramientas encargadas de crear los objetos nuevos
deben conocer las clases concretas de los objetos que van a instanciar
puesto que pertenecean a la jerarquía de figuras y son particulares para la
aplicación del editor gráfico.
o Problema 2: Si tenemos una acción (subclase herramienta) para crear un
rectángulo, tendremos que tener otra para crear un círculo, etc. Por lo
tanto si existen 200 objetos diferentes tendremos 200 clases de acción.
o Solución: En primer lugar establecer sólo una clase que se encargue de la
creación de los objetos de la jerarquía (todas las instancias). Para que
además la herramienta de creación no tenga que conocer a todos los
posibles tipos de instancia de la jerarquía, la herramienta de creación va a
construir los nuevos objetos de forma indirecta. Es decir la herramienta
de creación se inicializa con una instancia de las subclases gráfica y es a
las subclases gráficas a las que le corresonde obtener una copia de sí
mismas si se desea crear objetos de ese tipo.
Patrones de diseño Máster en Bases de Datos e Internet
-55-
Nótese el método que hay que introducir en la superclase Graphic para
permitir la réplica de los objetos.
• Aplicabilidad:
o Cuando un sistema debe ser independiente de la forma en que sus
productos son creados, compuestos y representados y …:
Las clases a instanciar son específicas en tiempo de ejecución.
Sólo existe un número pequeño de combinaciones diferentes de
estado para las instancias de una clase.
• Estructura:
• Participantes:
o Prototipo o Prototype: Declara la interfaz para clonarse.
Patrones de diseño Máster en Bases de Datos e Internet
-56-
o PrototipoConcretoX o ConcretPrototypeX: Implementa la operación de
clonarse.
o Cliente o Client: Crea un nuevo objeto solicitándole al prototipo que se
clone.
• Colaboraciones entre participantes: El cliente solicita a un objeto prototipo
que se replique (que se clone), es decir que se cree una copia de si mismo.
• Consecuencias:
o Oculta las clases del producto al cliente.
o Permite que el cliente trabaje con clases dependientes de la aplicación sin
cambios en este.
o Especificación de nuevos objetos mediante el cambio de sus valores.
o Especificación de nuevos objetos mediante la variación de su estructura
mediante el cambio del prototipo de modo que el cliente no se vea
afectado.
o Reducción del número de subclases. El patrón prototipo te permite a ti
instanciar un nuevo clon a partir del prototipo en vez de pedir al método
de fabricación que cree una nueva instancia, por lo tanto no necesitas una
jerarquía de clases creadoras.
o Configuración dinámica de una aplicación. Es posible añadir y eliminar
productos en tiempo de ejecución. Algunos entornos en tiempo de
ejecución te premiten la carga de clases de forma dinámica. El patrón
prototipo es la clave para explotar tales facilidades. (Ejemplo: Creación
del botón casa)
• Implementación:
o Uso de un gestor de prototipos. En este patrón surge el problema de
quién crea los prototipos para proporcionárselos al cliente de modo que
este no sea dependiente de las jerarquías. En general debe ser un objeto
que tenga que conocer la jerarquía y se la proporcione a los clientes
(puede haber más de uno), este objeto se conoce como el gestor de
prototipos. El gestor de prototipos tiene que proporcionar al cliente
métodos para que el cliente seleccione el prototipo que estime oportuno,
por ejemplo un método Producto crea(String tipoObjeto,
Patrones de diseño Máster en Bases de Datos e Internet
-57-
otraInformación);. Si en lugar de pasar un simple String con un nombre
se establecen especificaciones más complejas el patrón prototipo
degenerará en el patrón Negociador de productos o Product Traider en
donde el negociador es un gestor de prototipos.
o Implementación de la operación de clonación. En los objetos compuestos
esto puede ser un problema. Por ejemplo si clonamos un objeto decorado
(ver patrón decorador) de qué se hace copia del envoltorio exterior o de
todo el conjunto, es decir copia las referencias o crea nuevos objetos para
el estado. En función de la decisión que se tome se modificará la
operación clonar().
o Inicialización del objeto clonado en caso de que la réplica necesite una
inicialización adicional. A veces no es factible crear la instancia y
replicar todo el estado del objeto que sirve como prototipo por ejemplo
en el caso de que el prototipo tenga una clave o identificador de instancia
o si hay una cierta parte del prototipo que no se puede clonar. Cuando se
requiere inicialización la opción más común:
Exportar a la superclase los métodos de inicialización. Esta
opción es válida si todas las figuras en la jerarquía tuviesen la
misma interfaz para realizar su inicialización. Ejemplo void
inicializar (string fichxml). Cada subclase debe redefinir el
método y extraer la información necesaria.
• Ejercicios:
o Ejercicio 1: Realiza un diagrama de objetos del código que se
proporciona de ejemplo.
o Ejercicio 2: Realiza un diagrama de secuencia del programa Main.
Cliente Negociador
Especifiación Producto
Patrones de diseño Máster en Bases de Datos e Internet
-58-
o Ejercicio 3: Buscar información de la interfaz java Cloneable y modificar
el ejemplo proporcionado para usarla en lugar de emplear el método
clonar().
o Ejercicio 4: Modificar el ejemplo propocionado para permitir objetos
compuestos. Usar el patrón composición.
Patrón Singleton o Instancia Única
• Clasificación: Creacional.
• Propósito: Se asegura de que una determinada clase sólo tiene una instancia y
proporciona un punto de acceso a dicha instancia.
• Motivación:
o Existen múltiples ejemplos en donde sólo se requiere tener una instancia
de una clase, por ejemplo en el caso del patrón anterior sólo
necesistaremos una instancia del gestor de prototipos, o si tenemos
muchas impresoras en general sólo necesitaremos un único gestor de
impresión, muchas conexiones pero un único gestor de conexión etc.
o Problema: Nos interesa facilitar el acceso a ese objeto y que ese objeto
sea único, es decir exista una sola instancia de un determinado tipo de
clase.
o Solución 1: Mantener una variable global para facilitar el acceso. De este
modo no resolvemos el problema porque siempre podemos instanciar
múltiples objetos en variables locales aunque si es cierto que es de fácil
acceso.
o Solución 2: Hacer responsable a la propia clase de la instancia única:
Restringiendo el acceso al constructor de modo que una vez
creada una instancia ya no se puedan crear más.
Proporcionando un mecanismo para acceder a la instancia si esta
ya ha sido creada y sino que la cree en ese momento.
• Aplicabilidad:
o Debe existir una única instancia de una clase, y ésta debe ser accesible a
los clientes desde un punto de acceso bien conocido.
Patrones de diseño Máster en Bases de Datos e Internet
-59-
o La única instancia puede ser extendida (subclase), y los clientes deberían
poder usar la instancia extendida sin modificar su código.
• Estructura:
• Participantes:
o Instancia única o Singleton: Define un método de clase que permite a los
clientes acceder a la instancia única y normalmente también es la
responsable de crear su única instancia.
• Colaboraciones entre participantes: Los clientes acceden a la instancia del
Singleton a través de la operación definida a tal fin (instance()).
• Consecuencias:
o Acceso controlado a la instancia única.
o Reduce el espacio de nombres al evitar variables globales.
o Permite el refinamiento de operaciones y representación mediante el uso
de herencia. En este caso en lugar de tener una única instancia única de
ella misma tiene una instancia única de una subclase. En este caso se usa
la instancia de la subclase con la interfaz de la superclase.
o Permite un número variable de instancias.
o Más flexible que las operaciones de clase.
• Implementación:
o Asegurar la unicidad de la instancia de la clase.
o Extender la clase InstanciaUnica o Singleton:
El método de clase instacia conoce las subclases de la jerarquía y
crea la instancia deseada.
Establecer algún mecanismo para registrar las subclases.
Patrones de diseño Máster en Bases de Datos e Internet
-60-
o En Java:
Declarar el constructor como privado y además establecer un
atributo como privado para almacenar la instancia. Para
inicializar el atributo privado emplear un bloque estático.
Establecer un método público que proporcione la instancia
correspondiente al atributo privado de la clase.
• Ejercicios:
o Ejercicio 1: Probar el ejemplo de código proporcionado para el patrón
Instancia única y analizarlo.
Patrón Factory Method o Fabricación
• Clasificación: Creacional.
• Propósito: Define la interfaz para crear un objeto, pero deja que las subclases
decidan que clase concreta se debe instanciar.
• Motivación:
o Framework para apliacaciones que permiten presentar múltiples
documentos al usuario; donde existen dos abstracciones: Aplicación y
Documento. Para una aplicación específica, se especializan las interfaces
Aplicación y Documento.
o Problema: La abstracción (o interfaz) Aplicación conoce cuándo se debe
crear un documento pero no qué documento crear puesto que eso
depende de la aplicación específica que se desarrolla empleando el
framework, por ejemplo un documento de Word o un documento de
texto.
o Solución 1: Dar en la superclase o clase abstracta una implementación
por defecto del método crear documento y que las subclases lo redefinan.
Esta solución tiene la siguiente desventaja:
Puede ser que por cada aplicación concreta necesitemos un tipo
de documento concreto por lo que la subclase de documento por
defecto puede no ser nunca empleada.
o Solución 2: Usar el patrón prototipo, pero esto requiere que la jerarquía
de productos colabore.
Patrones de diseño Máster en Bases de Datos e Internet
-61-
o Solución 3: Asigna a un método abstracto la responsabilidad de crear un
documento concreto, separando esta responsabilidad del framework.
• Aplicabilidad:
o No se puede anticipar la clase de objetos que se tienen que crear.
o Una clase quiere que sus subclases especifiquen que objetos se deben
crear.
o Clases que delegan la responsabilidad a una de las subclases
colaboradoras y se desea localizar el conocimiento de qué sublcases es la
encargada.
• Estructura:
• Participantes:
o Producto o Product: Definde la interfaz de los objetos creados por el
método de fabricación.
o ProductoConcreto o ConcreteProduct: Implementa la interfaz de los
productos.
o Creador o Creator o Factoría o Factory: Declara el método de
fabricación y opcionalmente pudede definir una implementación por
defecto que construye un producto concreto. Puede utilizar el método de
fabricación.
Patrones de diseño Máster en Bases de Datos e Internet
-62-
o CreadorConcreto o ConcreteCreator o FactoríaConcreta o
ConcreteFactory: Redefine el método de fabricación para devolver una
instancia de un producto concreto.
• Colaboraciones entre participantes: El creador emplea el método de
fabricación redefinido por sus sublcases para utilizar la instancia del producto
concreto apropiada.
• Consecuencias:
o Elimina la necesidad de incluir clases específicas de la aplicación en
código más general dando mayor potencia de reutilización del
framework.
o Mayor flexibilidad dado que se proporciona un mecanismo a las
subclases para introducir una versión másextendida del producto.
o Conecta jerarquías paralelas.
o Desventaja: Puede obligar a extender la clase creadora sólo para crear un
producto concreto. Si esto es un problema puede emplear otra solución
como por ejemplo el patrón prototipo.
• Implementación:
o Dos variantes:
El creador es una clase abstracta y no proporciona
implementación por defecto para el método (necesario extender al
creador)
Patrones de diseño Máster en Bases de Datos e Internet
-63-
El creador es una clase concreta y define un producto concreto
por defecto (flexibilidad para cambios futuros).
o Métodos de fabricación parametrizados.
Un único método puede crear distintos productos en base a los
parámetros del método de fabricación. (Solución más común.).
• Ejercicios:
o Ejercicio 1: Probar el ejemplo de código proporcionado para el patrón
fabricación y analizarlo.
Patrón Abstract Factory o Fábrica Abstracta
• Clasificación: Creacional.
• Propósito: Interfaz para la creación de familias de objetos relacionados sin
especificar sus clases concretas.
• Motivación:
o Interfaz de usuario con múltiples look-and-feels (Motif, Presentation
Manager, Windows, ...)
o Cada Look-and-feel define su propio juego de components (widgets:
botones, ventanas, barras de desplazamiento, ...)
o Problema: Por razones de portabilidad el resto del sistema no debe hacer
referencia a componenetes concretos.
o Solución: Crear una clase abstracta con un método de fabricación para
cada componente (fábrica abstracta) y una clase abstracta por
componente. El cliente creará los componentes mediante la fábrica
abstracta. De modo que la fábrica de componentes garantiza el uso
consistente de cmponentes de un mismo look-and-feel.
Patrones de diseño Máster en Bases de Datos e Internet
-64-
• Aplicabilidad:
o Un sistema debe ser independiente de la forma en que sus productos son
creados, compuestos y representados.
o Un sistema debe ser configurado con una de muchas familias de
productos disponibles.
o Una familia de productos son diseñados para su uso conjunto, y se
requiere asegurar este uso conjunto.
o Se desea proporcionar una biblioteca de productos presentando su
interfz, pero no su implementación.
• Estructura:
• Participantes:
o Fábrica abstracta o AbstractFactory: Declara la interfaz para las
operaciones que crean productos abstractos (métodos de fabricación)
o Fábrica Concreta o ConcretFactory: Implementa los métodos de
fabricación de productos concretos.
o Producto abstracto o AbstractProduct: Declara la interfaz utilizada por el
cliente par un tipo de producto concreto.
Patrones de diseño Máster en Bases de Datos e Internet
-65-
o ProductoConcreto o ConcreteProduct: Define un producto creado por el
método de fabricación de una fábrica concreta. Implementa la interfaz
del producto abstracto.
o Cliente o Client: Usa sólo las interfaces declaradas por la fábrica
abstracta y los productos abstractos.
• Colaboraciones entre participantes: Normalmente se crea una única fábrica
concreta que se encarga de crear los productos concretos, mientras que la fábrica
abstracta difiere la creación de productos a sus subclases.
• Consecuencias:
o Aísla clases concretas (no aparecen en el código del cliente).
o Facilita el intercambio de familias de productos.
o Simplifica consistencia entre productos.
o Difícil añadir nuevas clases de productos.
• Implementación:
o Las fábricas usualmente suelen se instancias únicas.
o La creación de productos puede realizarse por el método de fabricación
habitual o mediante el patrón prototipo para evitar extender la fábrica
abstracta.
o Flexibilizar la fábrica mediante la parametrización del método de
fabricación:
El método de fabricación puede crear diferentes tipos de
componenetes en base a los parámetros del método.
El cliente debe realizar una conversión tras crear el producto
(downcasting).
En la mayoría de los lenguajes no hay ninguna relación formal
entre valores de los parámetros y productos creados, exceptuando
el código fuente.
Patrón Builder o Constructor
• Clasificación: Creacional.
Patrones de diseño Máster en Bases de Datos e Internet
-66-
• Propósito: Separa la construcción de un objeto complejo de su representaicón,
de modo que el mismo proceso de construcción permite crear diferentes
representaciones.
• Motivación:
o Lector de documentos en formato RTF que lo convierte a diferentes
formatos (ASCII; TEX;...).
o Dejar abierta la posibilidad de nuevos tipos de conversión: debería ser
sencillo añadir una nueva conversión sin modificar el lector.
o Solución: Configurar el lector con un objeto responsable de convertir
cada fragmento del documento RTF al formato destino.
o Las subclases de la clase constructora especializan la construcción para
los distintos formatos
• Aplicabilidad:
o El algoritmo para crear un objeto complejo debe ser independiente de las
partes que constituyen el objeto y de cómo son ensambladas.
o El proceso de construcción debe premitir distintas representaciones del
objeto construido.
• Estructura:
Patrones de diseño Máster en Bases de Datos e Internet
-67-
• Participantes:
o Constructor o Builder: Especifica la interfaz para la creación de las
partes de un Producto.
o ConstructorConcreto o ConcreteBuilder: Implementa la interfaz del
constructor para construir y ensamblar las diferentes partes del producto.
Además almacena el producto en construcción y proporciona una
interfaz para recuperar el producto construido.
o Director o Director: Construye un objeto utilizando la interfaz del
constructor.
o Producto o Product: Objeto concreto a construir.
• Colaboraciones entre participantes:
o El cliente crea el objeto director y lo configura con el constructor
deseado.
o El director notifica al constructor la parte del producto que debe ser
creada.
o El constructor añade partes al producto, de acuerdo con las peticiones del
director.
o El cliente recupera el producto final del constructor.
Patrones de diseño Máster en Bases de Datos e Internet
-68-
• Consecuencias:
o Permite variar la representación interna de un producto.
o Aísla el código de la construcción y la representación.
o Proporciona un control más detallado del proceso de construcción.
Patrones de diseño Máster en Bases de Datos e Internet
-69-
PATRONES DE COMPORTAMIENTO
Patrón Chain of Responsability o Cadena de Responsabilidad
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Posibilidad de enviar (y/o gestionar) una petición a más de un objeto
mediante el encadenamiento de los receptores.
• Motivación:
o Sistema de ayuda sensible al contexto de una interfaz gráfica donde el
usuario puede solicitar ayuda de cualquier componente o parte de la
interfaz. Si la parte seleccionada tienen información específica debe
presentarla, en caso contrario debe presentar un mensaje relacionado con
el contexto más próximo (sucesor) de la parte seleccionada. En general el
contexto más próximo será el que lo contiene el elemento.
o Problema: El objeto que inicia la petición no conoce a priori que objeto
proporciona la ayuda, es decir no sabe si su sucesor más cercano
resolverá la petición o será otro más alejado.
o Solución: Desacoplar el emisor de la petición de los receptores (receptor
implícito, es decir el que realmente resuelve la petición). Se establece
una cadena de objetos que delegan la petición hasta que uno se hace
cargo. Por lo tanto la respuesta a la petición dependerá tanto del
componente en que se realice la petición como del contexto en que se
encuentre éste.
Patrones de diseño Máster en Bases de Datos e Internet
-70-
o La alternativa a al solución de la cadena de responsabilidad es que cada
objeto conociese la forma de resolver el servicio. Esto implicaría
sobrecargar el objeto en concreto con más cosas de las necesarias y
llevaría en muchos casos a la duplicidad de código. Otra solución sería
conocer a priori el objeto que resuelve la petición pero esto último
provoca acoplamiento entre el que inicia el servicio y el que lo resuelve,
por lo cual es más difícil de mantener. El patrón está pensado para que la
estructura de la cadena pueda variar dinámicamente y que además el
mensaje pueda ir modificándose.
o Para realizar la delegación entre objetos de la cadena es necesario tener
una estructura que los relacione por ejemplo la asociación manejador o
handler.
Patrones de diseño Máster en Bases de Datos e Internet
-71-
• Aplicabilidad:
o Más de un objeto puede manejar la petición y no se conoce a priori cuál
de ellos va a resolverla.
o No se desea identificar explícitamente el receptor de una petición, sino
que le envías la petición a un conjunto.
o Los objetos que pueden manejar la petición varían dinámicamente.
• Estructura:
• Participantes:
o Manejador o Handler: Define la interfaz para manejar peticiones y
normalmente también define el enlace al sucesor en la cadena. En
general también determina la resolución por defecto de la petición sino
existe un objeto en quien delegar.
o ManejadorConcreto o ConcreteHandler: Maneja las peticiones de las
que es responsable. Si no puede gestionar la petición, la redirige a su
sucesor.
o Cliente o Client: Envía una petición a algún manejador concreto de la
cadena.
• Colaboraciones entre participantes:
Patrones de diseño Máster en Bases de Datos e Internet
-72-
o Cuando un cliente inicia una petición, dicha petición se propaga a través
de la caden hasta que un manejador concreto asume la responsabilidad de
gestionarla y en ese momento corta la cadena de responsabilidad.
• Consecuencias:
o Reduce el acoplamiento entre objetos, puesto que reduce las
dependencias. En cualquier caso al mismo tiempo acarrea una pequeña
penalización de la eficiencia por los niveles de indirección introducidos
que son más acusados cuanto mayor sea la delegación en la cadena.
o Flexibilidad añadida a la hora de asignar responsabilidades a los objetos.
o La recepción de la petición no está garantizada puesto que quizás ningún
objeto de la cadena de responsabilidad resuelve el servicio. Por lo tanto
es necesario saber cuál es el final de la cadena de responsabilidad y si en
ese momento no se puede resolver la petición devolver algún tipo de
error, mensaje informativo o valor por defecto.
• Implementación:
o Cadena de sucesores: Definir nuevos enlaces para los sucesores o
emplear enlaces existentes como por ejemplo los definidos en el patrón
composición con variante para referenciar el padre. En general si no
exiten enlaces para los sucesores se crea una asociación en la superclase
de los objetos que intervienen en la cadena. Esta superclase y asociación
permite establecer el código para realizar la asociación y delegación de la
petición en la superclase de modo que cada una de las clases concretas si
quiere manejar la petición deber reescribir el método correspondiente,
sino actuará como la superclase.
o Conexión de sucesores.
o Representación de las peticiones.
Un método por tipo de petición.
Único método parametrizado para distinguir diferentes tipos de
peticiones:
Como parámetro del método poner un id que nos indique
el tipo de petición. Mala solución porque si alguna de las
peticiones implica parámetros entonces a parte de ese
Patrones de diseño Máster en Bases de Datos e Internet
-73-
identificador tendríamos que poner en cualquier petición
todos los parametros de todas las posibles peticiones que
no usuamos
Tener como parámetro del método que maneja las
peticiones un objeto petición que actúa como superclase
de los diferentes conjuntos de parámetros de las
peticiones.
o Se están creando objetos artificiales que no tienen
un comportamiento asociado, solamente
almacenan un conjunto de parámetros.
o No es necesario recompilar las clases de la cadena
que no manejan la petición si se añade una nueva
petición. Además así no se sobrecargan esas clases
con métodos que no saben resolver.
o Ejercicio 1: Realiza un diagrama de objetos del código que se
proporciona de ejemplo.
o Ejercicio 2: Realiza un diagrama de secuencia del programa Main.
o Ejercicio 3: Fusiona el código del ejemplo de unidades de combate del
patrón decorador con el código propocionado en este bloque. A
continuación reflexiona sobre las diferencias entre el patrón decorador y
el patrón cadena de responsabilidad.
Patrón State o Estado
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Permite a un objeto modificar su comportamiento al cambiar su
estado interno, de modo que “el objeto concreto en apariencia cambia de clase”.
• Motivación:
o Problema: Supongamos que disponemos de una clase que representa
una conexión a una base de datos o una conexión de red. Un objeto en
concreto de esa clase puede estar en diferentes estados: Establecida,
Cerrada o Transmitiendo. Al recibir una petición, el objeto se comporta
Patrones de diseño Máster en Bases de Datos e Internet
-74-
de modo distinto en base a su estado interno. Por ejemplo si la conexión
está Cerrada y se intenta realizar una consulta SQL se producirá un
mensaje de error, sin embargo si el estado de la conexión es Establecida
nos propocionará los datos correspondientes si realizamos correctamente
la consulta.
o Solución 1: Extender la clase conexión con subclases que representen la
conexión en distintos estados
Problema: Los objetos tienen que cambiar dinámicamente de
clase cuando pasen de un estado a otro.
o Solución 2: Tener una única clase conexión y en cada uno de los
métodos establecer condiciones (switch, case, if, etc.) para determinar
dentro de los métodos lo que se debe hacer en función del estado.
Problema: Más complejo el código y el mantenimiento de la
clase.
o • Solución 3: Introducir una superclase abstracta que representa a los
estados de la conexión de red. La superclase define la interfaz de los
métodos dependientes del estado. Esta superclase es extendida con
subclases que implementan el comportamiento específico de cada uno de
los estados concretos.
Problema: Tiene el mismo problema que la solución 1.
o Solución 4: La clase conexión mantiene una referencia a un objeto
estado en el que delega el comportamiento dependiente del estado en que
se encuentra la conexión. El objeto concreto del que mantiene la
referencia la conexión en un determinado instante representa el estado
actual de dicha conexión. Para cambiar de estado simplemente se cambia
la asociación entre la clase conexión y un objeto de la clase estado.
La clase estado es un clase abstracta (es decir que no pueden existir
instancias de dicha clase) que declara un interfaz común a todas las
subclases para representar diferentes estados operacionales. Por lo tanto,
la clase abstracta se extiende con subclases concretas que representan el
comporamiento específico en cada uno de los estados operacionales.
Patrones de diseño Máster en Bases de Datos e Internet
-75-
Problema: En los métodos dependientes del estado se pueden requerir
atributos de la clase TCPConnection:
• Solución a: Pensar la asociación _state como una relación
bidireccional. Esta solución suele ser difícil de mantener y
compleja.
• Solución b: Proporcionar el propio libro como parámetro
de llamada a un metodo.
• Aplicabilidad: El comportamiento de un objeto depende de su estado, y dicho
estado puede cambiar en tiempo de ejecución. Además también se puede aplicar
cuando existen clases con grandes sentencias condicionales múltiples
dependientes del estado del objeto y donde el estado se representa por 1 o más
constantes enumeradas.
• Estructura:
• Participantes:
o Contexto (Context): Define la interfaz para los clientes. Mantiene una
instancia de un estado concreto que define el estado actual del objeto
Patrones de diseño Máster en Bases de Datos e Internet
-76-
contexto. En el ejemplo motivador se corresponde con la clase
TCPConection.
o Estado (State): Define una interfaz para encapsular el comportamiento
asociado con un estado particular del contexto. En el ejemplo motivador
se corresponde con la clase TCPState.
o Estados Concretos (ConcreteState): Cada subclase implementa el
comportamiento asociado con un estado del contexto. En el ejemplo
motivador se corresponde con las clases TCPStateStablished, TCPClose
y TCPListen.
• Colaboraciones entre participantes:
o El contexto delega las partes de comportamiento específicos del estado al
objeto ConcreteState que tiene asociado en cada momento. Además el
contexto puede pasarse a sí mismo como argumento al objeto estado para
manejar una petición. De esta forma, el objeto estado puede acceder a
información del contexto si esta es requerida.
o La configuración de un contexto la puede realizar un cliente con objetos
estado pero en general los clientes utilizan el contexto como interfaz, sin
necesidad de manejar objetos estado directamente. Es más una vez el
contexto está configurado inicialmente, el cliente no debería tratar con
los objetos estado directamente. Además en el constructor de la clase
contexto se puede indicar un estado inicial.
Por otro lado tanto el contexto como los estados concretos pueden
decidir cambiar el estado actual bajo la política concreta de cambio de
estado.
• Consecuencias:
o Localiza y separa el comportamiento específico de cada estado
facilitando añadir nuevos estados y transiciones pero haciendo que el
modelo sea menos compacto puesto que aumenta el número de clases.
o Encapsula el comportamiento asociado a un estado concreto en un clase
particular y deja en la clase contexto sólo operaciones que no dependen
del estado, lo cual facilita el mantenimiento.
Patrones de diseño Máster en Bases de Datos e Internet
-77-
o Hace explícitas las transiciones entre estados, mientras que si se opta por
codificar el estado con valores internos en la clase contexto y sentencias
condicionales esto sería implícito. Es decir, las transiciones entre estados
se mostrarían sólo mediante la asignación de determinados valores a
variables.
o Bajo ciertas circunstancias, es posible la compartición de objetos estado
por varios objetos contexto. Por ejemplo cuando los objetos estado no
tienen variables instanciadas, es decir el objeto estado es como un “tipo
de datos” (patrón objeto ligero o flyweight).
• Implementación:
o ¿De quién es la responsabilidad de efectuar transición entre estados? Esto
no se especifica en el patrón. En general cuando los criterios son fijos los
cambios de estado suelen ser responsabilidad de la clase contexto. Sin
embargo, se puede permitir que las sublcases estado especifiquen su
propio estado sucesor. Esto último requiere que las subclases estado
conozcan el objeto contexto y que el contexto disponga de un método
que les permita a dichas subclases cambiar su estado actual
explícitamente.
o Creación y destrucción de objetos estado.
Crear y destruir cada vez que es necesario. Posiblemente siendo
el contexto el que se encargue de esto. Evita crear objetos que no
son frecuentemente usados.
Crear al principio y no destruir. Esto sólo es posible cuando los
estados se conocen a priori y no se van a cambiar en tiempo de
ejecución. Da lugar a dos relaciones: EstadosPosibles y
EstadoActual.
Emplear el patrón instancia única para la creación de estados.
o Herencia dinámica.
• Código ejemplo:
o Ejercicio 1: Analiza cuales son los objetos que se porporcionan en el
código de ejemplo y determina cuál es la función de cada uno de ellos.
Patrones de diseño Máster en Bases de Datos e Internet
-78-
o Ejercicio 2: ¿Qué patrón o patrones se están usando en la
implementación del ejemplo además del patrón estado o State?
o Ejercicio 3: ¿Cuál es la visibilidad del método
establecerEstado(EstadoLibro estado) de la clase libro? ¿Podría tener
otra visibilidad? ¿Qué implicaría?
Patrón Strategy o Instancia Estrategia
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Define, encapsula y hace intercambiables a una familia de
algoritmos, de modo que un algoritmo puede variar independientemente del
cliente que lo usa. Además hace intercambiables a los diferentes algoritmos con
la misma funcionalidad.
• Motivación:
o En el contexto de un editor de textos se dispone de diversos algoritmos
para particionar un texto en líneas (justificado, alineado a izquierda,
alineado a derecha, con palabras partidas, etc. ) siendo deseable separar a
las clases clientes de las clases algoritmos de partición por las siguientes
razones:
Los clientes que incluyen el código para particionar en líneas son
más grandes y más difíciles de mantener, especialmente si
soportan múltiples algortimos de particionamiento.
No todos los algoritmos son necesarios en todos los casos. De
modo que no queremos que los clientes soporten algoritmos que
no van a necesitar.
Es difícil añadir nuevos algoritmos o modificar los existentes si el
algoritmo forma parte del cliente.
Se produce duplicidad de código si existen diferentes clientes
distintos que requieren el particionamiento de líneas.
o Solución: Definir clases que encapsulan a las diferentes estrategias de
particionamiento en una jerarquí diferente.
Patrones de diseño Máster en Bases de Datos e Internet
-79-
Cada una de las clases concretas Compositor representan un algoritmo,
de modo que el cliente (Composition) puede reemplazar el algoritmo que
emplea o bien estáticamente o bien dinámicamente.
Este patrón también es útil cuando el algoritmo con el que se está
trabajando es complejo y requiere muchas estructuras de datos que se
quieren aislar.
Se ve que la estructura es similar al patrón anterior (estado) pero los
propósitos por los que surge son distintos. En el patrón estado existe una
dependencia mucho más fuerte que en el patrón estrategia puesto que por
ejemplo una conexión no puede existir si no tiene estado asociado pero el
editor puede existir sin un algoritmo de particionamiento de líneas.
Además los algoritmos pueden ser usados por otros tipos de clientes.
• Aplicabilidad:
o Muchas clases relacionadas se diferencian únicamente en su
comportamiento, de modo que aparece una superclase con el
comportamiento común y se accede según la interfaz de la superclase.
o Necesarias distintas variantes de un algoritmo.
o Un algoritmo utiliza información que los clientes no deberían conocer. El
patrón evita la exposición de estructuras de datos dependientes del
algoritmo.
o Una clase define múltiples comportamientos mediante una serie de
instrucciones condicionales. En lugar de emplear las estructuras
condicionales, mover el código de dichas estructuras a clases propias
donde se realice la estrategia pertinente.
Patrones de diseño Máster en Bases de Datos e Internet
-80-
• Estructura:
• Participantes:
o Contexto (Context): Es el elmento que usa los algoritmos por lo tanto
va a delegar en la jerarquía. Está configurado con una estrategia concreta
mediante una referencia al objeto estrategia correspondiente. Puede
definir una interfaz que permita a la estrategia el acceso a sus datos.
o Estrategia (Strategy): Declara una interfaz com´un para todos los
algoritmos soportados. El contexto utiliza este interfaz para invocar el
algoritmo definido por una estrategia concreta.
o Estrategia Concreta (ConcreteStrategy): Implementa el algoritmo
utilizando la interfaz definida por la estrategia.
• Colaboraciones entre participantes:
o Es necesario el intercambio de información entre Estrategia y Contexto
para implementar el algoritmo elegido:
Parámetros de los métodos de la estrategia: En este caso al
algoritmo elegido se le pasa sólo la información que necesita para
realizar la operación requerida.
En ocasiones, como ocurría en el patrón Estado, el contexto se
pasa a sí mismo a la estrategia. Sin embargo si se opta por esta
opción se está haciendo más difícil la reutilización de los
algoritmos en otros puntos debido a que se están uniendo las dos
jerarquías (la cliente y la de estrategias).
o Los clientes del contexto normalmente configuran a éste con una
estrategia concreta. A partir de ahí, sólo se interactúa con el contexto.
• Consecuencias:
Patrones de diseño Máster en Bases de Datos e Internet
-81-
o La herencia puede ayudar a factorizar las partes comunes de las familias
de algoritmos.
o Alternativa a la extensión de contextos cada uno con una estrategia o
algoritmo. Además al permitir la evolución independiente se obtiene la
posibilidad de realizar cambios dinámicos de algoritmos.
o Reducción de instrucciones condicionales.
o Diferentes opciones de implementación para un mismo algoritmo sin
modificar el código de la clase.
o Los clientes deben conocer las diferentes estrategias, a diferencia de lo
que ocurría en el patrón estado, y en base a la política estratégica decidir
cuál de las estrategias se va a aplicar.
o Existe una pequeña penalización en la comunicación entre estrategia y
contexto, como sucede siempre que se pasa de una clase monolítica a
usar la delegación, puesto que se produce una indirección.
o Incremento del número de objetos.
• Implementación:
o Para la definición de la interfaz entre estrategia y contexto existen tres
formas básicas:
Pasar como parámetro la información necesaria para la estrategia
de forma explícita. Esta es la opción más comúnmente usada.
Pasar como parámetro el contexto y dejar que la estrategia
explícitamente pida la información que necesita. Es la opción
menos usada con el patrón estrategia aunque es común con el
patrón estado.
Mantener en la estrategia una referencia al contexto, es decir,
hacer la asociación bidireccional.
o Cuando los objetos estrategia son opcionales cuando se vaya a emplear
una determinada estrategia es necesario realizar la comprobación de si se
dispone de ella. Otra posibilidad es definir en la jerarquía estrategia la
estragegia nula que es la que se asigna por defecto.
• Código ejemplo:
Patrones de diseño Máster en Bases de Datos e Internet
-82-
o Ejercicio 1: Analiza cuáles son los objetos que se porporcionan en el
código de ejemplo y determina cuál es la función de cada uno de ellos.
o Ejemplo 2: Amplia el código del ejemplo para proporcionar la estrategia
de ordenación Quicksort.
Patrón Observer u Observador
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Definir una dependencia uno-a-muchos entre objetos de un modelo y
sus vistas de tal forma que cuando el objeto cambie de estado, todos sus objetos
dependientes sean notificados y actualizados automáticamente.
• Motivación:
o Las aplicaciones de hoy en día, en general, se dividen en 3 partes o
capas: Vista (interfaz del sistema), Modelo (lógica de la aplicación) y
Almacenamiento o Persistencia (almacena de forma persistente la
inforamción relacionada con el modelo). Estas tres partes tratan de ser lo
más independientes posible aunque tienen puntos de conexión. De este
modo se permite cambiar la interfaz gráfica de las aplicaciones (por
ejemplo de escritorio a Web) o el modelo de almacenamiento empleado
(por ejemplo de ficheros XML a una base de datos relacional) sin afectar
a las demás capas.
o En estos casos y otros existe una necesidad de consistencia entre clases
relacionadas pero manteniendo bajo acoplamiento. Por ejemplo: Separar
componentes GUI de los objetos que mantienen los datos de la
aplicación para que sean reutilizables independientemente.
Patrones de diseño Máster en Bases de Datos e Internet
-83-
o Solución 1: Se puede pensar que periódicamente los objetos presentación
preguntan al objeto subject por su estado y si este ha modificado lo
actualizan.
o Problema: Esto no parece lógico porque se puede llegar a sobrecargar al
objeto subject aunque este cambie con muy poca frecuencia su estado. Es
más lógico que cuando se cambie el estado en subject este notifique a
todos sus observadores el cambio.
o Solución 2: El comportamiento de los observadores (hoja de cálculo,
diagrama de barras,...) depende del sujeto observado, que debería
notificar cualquier cambio en su estado. Además el número de
observadores no está limitado.
De modo que el comportamiento sería:
ObtenerEstado()
Actualizar()CambiarEstado()
*Modelo ObtenerEstado() MetodosCambio()
Vista Actualizar()
:Controlador :Modelo :Vista
Patrones de diseño Máster en Bases de Datos e Internet
-84-
En este ejemplo sólo se ha considerado una vista pero si hubiese más el
modelo tendría que notificar la actualización a todas las vistas.
Además el modelo debería disponer de métodos para que más vistas
puedan ser añadidas dinámicamente y también eliminadas; por ejemplo,
si se cierra una ventana.
Nótese que el sujeto no es consciente de cuántos observadores van a
estar afectados por un cambio en concreto en su estado, puesto que no
debe saber nada de su aspecto y comportamiento. Lo único que debe
saber el sujeto es que los observadores disponen de un método actualizar
al que debe llamar cuando cambie de estado.
• Aplicabilidad:
o Una abstracción tiene dos aspectos diferentes, uno dependiente del otro.
Encapsular estos aspectos en objetos separados permite su variación y
reutilización de modo independiente.
o Cuando una modificación en el estado de un objeto requiere cambios de
otros, y no se desea conocer cuantos objetos deben ser cambiados.
o Cuando un objeto debería ser capaz de notificar a otros objetos sin hacer
ninguna suposición acerca de los objetos notificados.
• Estructura:
Patrones de diseño Máster en Bases de Datos e Internet
-85-
o La relación _subject se realiza entre los objetos concretos y no entre las
interfaces, como en el caso de la relación _observers; es decir, la relación
_observers no es bidireccional. Esto tiene que ser necesariamente así
porque el ConcreteObserver tiene que ser capaz de determinar las
características del ConcretSuject que le interesan y cuales no.
Se podría optar por hacer la asociación observadores bidireccional pero
en ese caso en el observador concreto tendríamos que hacer un
downcasting al sujeto concreto.
En cualquier caso la asociación sujeto se puede evitar si en el método
actualizar se pasa como parámetro el sujeto de forma explícita (actualizar
(Sujeto s)) de modo que se crea una dependencia temporal en tiempo de
ejecución pero no en tiempo de compilación. Nótese que en este caso
también es necesario realizar un downcasting.
• Participantes:
o Sujeto (Subject): Conoce a sus observadores y proporciona una interfaz
para agregar (attach) y eliminar (detach) observadores del propio Sujeto.
o Observador (Observer): Define un método utilizado por el Sujeto para
notificar cambios en su estado (update).
o SujetoConcreto (ConcreteSubject): Mantiene el estado de interés para
los observadores concretos. Notificándo a los observadores el cambio en
su estado.
o ObservadorConcreto (ConcreteObserver): Mantiene una referencia al
sujeto concreto debido a que parte de su estado debe permanecer
consistente con el estado del sujeto. Para lograr esta consistencia,
implementa la interfaz de actualización.
• Colaboraciones entre participantes:
o El sujeto concreto notifica a sus observadores cada vez que se modifica
su estado. Esta responsabilidad de notificar la hereda de su padre
(sujeto).
o Tras ser informado de un cambio en el sujeto concreto, un observador
concreto interroga al sujeto para modificar la percepción que tiene de
dicho sujeto.
Patrones de diseño Máster en Bases de Datos e Internet
-86-
• Consecuencias:
o Abstrae acoplamiento entre sujeto y observador, de modo que se pueden
modificar y reusar las jerarquías de sujestos y observadores
independientemente. Además permite la addición de nuvas clases
observadores sin para ello tener que modificar a los sujetos ni a los
demás observadores.
o El sujeto no necesita especificar los observadores afectados por un
cambio, es decir, cada sujeto sabe que tiene una lista de observadores
pero el sujeto concreto no conoce las clases observadores concretos. Por
lo tanto desconoce a cuales de sus observadores le va a afectar un
determinado cambio en su estado.
o Desconocimiento de las consecuencias de una actualización. El sujeto
concreto emite una comunicación broadcast a todos sus observadores y
son estos los que preguntan el estado al sujeto concreto y determinan si
se modifican o no.
• Implementación:
o Implementación asociación sujeto-observadores. En un principio la
asociación se presenta con una estructura de datos en el sujeto como por
ejemplo una lista, array, etc. Sin embargo, si se está actuando en un
escenario en el cual en la mayoría de los casos los sujetos no tienen
observadores esto produce una penalización por uso de una estructura
que no se está empleando en cuanto a espacio se refiere. Para evitar esta
Patrones de diseño Máster en Bases de Datos e Internet
-87-
penalización se propone un objeto intermedio que sea el que tenga en
cuenta la asociación aunque esto implique un mayor coste en el acceso a
los observadores. En el caso de emplear un intermediario el sujeto no
tiene la responsabilidad de actualizar a todos los observadores sino que
delega esta tarea en el gestor de observadores. Además si el gestor de
observadores fuese único se podría emplear un patrón instancia única.
Nótese que en caso de emplear un gestor de observadores debe existir un
método que a cada sujeto le permite actualizar los observadores que tiene
asociados. Además se debe señalar que se ahorra espacio en el Sujeto,
haciéndolo más ligero pero se penaliza en tiempo de ejecución puesto
que de este modo existen dos niveles de indirección en lugar de uno solo.
o Observación de más de un sujeto. En algunos casos los observadores
dependen del estado de más de un sujeto (de igual o de distinto tipo). En
este caso es necesario cambiar la cardinalidad de la relación sujeto o
tener varias relaciones sujeto.
Desde el punto de vista del funcionamiento del sujeto se funciona del
mismo modo pero no desde el punto de vista del observador puesto que
Sujeto Modificar() AñadirObservador(o)
Observador Actualizar()
Gestor de Observadores Actualizar(sujeto)
*
Patrones de diseño Máster en Bases de Datos e Internet
-88-
cuando se recibe una actualización se desconoce que sujeto la ha
provocado.
La postura clásica es recuperar el estado de todos los
sujetos que se tienen asociados.
Otra alternativa es indicar el sujeto que ha provocado la
actualización, para ello se puede pasar el sujeto como
parámetro del método actualizar. De este modo se puede
recuperar selectivamente la inforamción.
o Responsabilidad de inicio de la notificación:
Sujeto invoca la notificación tras ejecutarse un método que
cambie su estado.
Clientes del sujeto (posiblemente los propios observadores u
otros) son responsables de comenzar la notificación de
actualización cuando provoquen un cambio en el sujeto. Esto
suele suponer una complicación adicional en el cliente que, en
general, se debe evitar.
o Referencias inválidas tras borrar un sujeto. En los lenguajes donde es
necesario hacer explícita la gestión de memoria, como por ejemplo C++,
si produce un borrado de un sujeto concreto sin considerar los
observadores que tiene asociados puede provocar comportamientos
inesperados. Para evitar problemas antes de borrar un sujeto se debería
hacer una notificación especial a todos sus observadores.
Nótese también que antes de proceder al borrado de un observador se
debería eliminar este de la asociación de observadores del sujeto.
o Asegurar la consistencia del estado del sujeto antes de iniciar la
notificación. Es importante asegurarnos de que la notificación se lleve a
cabo cuando la transacción que implica el cambio en el sujeto se ha
finalizado. (Ver patrón plantilla).
o Evitar actualización dependiente del observador:
El sujeto notifica los cambios y los observadores piden
información necesaria para ver si se tienen que actualizar o no. Es
lo que se denomina pull model. Este modelo es ineficiente en
Patrones de diseño Máster en Bases de Datos e Internet
-89-
cuanto a que obliga a preguntar a los observadores aunque el
cambio no les vaya a afectar pero reduce el acomplamiento entre
jerarquías.
El sujeto envía información detallada sobre el cambio que ha
realizado, de este modo sólo los observadores a los que le afecta
el cambio se actualizarán. Es lo que se denomina push model.
Este modelo es más eficiente pero menos reusable.
o Especificación explícita de las modificaciones (push model).
• Código ejemplo:
o Ejercicio 1: Analiza las clases del ejemplo proporcionado y elabora un
diagrama de clases y de secuencia.
o Ejercicio 2: Observa que en el código de los diferentes observadores
concretos existen partes comunes que se pueden factorizar. Factoriza las
actuaciones comunes para evitar replicar código.
o Ejercicio3: Con la nueva implementación realiza un diagrama de
secuencia.
o Ejercicio 4: Java proporciona una implementación del patrón
observador. Analizar la documentación proporcionada en el javadoc de
las clases Observable y Observer del paquete java.util.
Patrón Iterator o Iterador
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Mecanismo de acceso a los elementos que constituyen una estructura
de datos sin exponer su representación interna; es decir, conocer los detalles
internos de la estructura.
• Motivación:
o Se desea acceder a los elementos de un contenedor de objetos (por
ejemplo, una lista enlazada) sin exponer su representación interna:
Solución: Añadir métodos que permitan recorrer la estructura sin
referenciar explícitamente su representación. Por ejemplo con un
vector, añadir elemento, acceder a la posición i-ésima.
Patrones de diseño Máster en Bases de Datos e Internet
-90-
Problema: Puede necesitarse más de una forma de recorrer la
estructura: se complica la interfaz de la clase. Por ejemplo, con
las listas tienes que añadir recorrer hacia atrás.
Problema: Si se necesita un recorrido no previsto es necesario
modificar la clase, que ya está funcionando o implementarlo en
las clases que usan esa nueva funcionalidad lo cual no es
reutilizable.
Solución: Mover la responsabilidad del recorrido a un objeto
iterador. Serparar la estructura de datos en dos partes, la que
contiene los propios datos y la que sabe en que posición nos
encontramos y como navegar a través de ella.
No tiene por qué limitarse a recorrer la estructura (por ejemplo,
filtrado).
Problema: Los clientes de la estructura de datos deben conocer la
estructura concreta para crear un iterador.
Solución: Generalizar los distintos iteradores en una superclase y
dotar a las estructuras de datos de un método de fabricación que
cree un iterador concreto.
Patrones de diseño Máster en Bases de Datos e Internet
-91-
• Aplicabilidad:
o Acceso al contenido de una estructura sin exponer su representación
interna.
o Distintos tipos de recorrido sobre la estructura.
o Interfaz uniforme para recorrer diferentes tipos de estructuras.
• Estructura:
• Participantes:
o Iterador (Iterator): Define la interfaz para recorrer y acceder al
agregado de elementos.
Patrones de diseño Máster en Bases de Datos e Internet
-92-
o Iterador Concreto (ConcreteIterator): Implementa la interfaz
propuesta por el Iterador. Mantiene la posición actual en el recorrido de
la estructura.
o Agregado (Aggregate): Define la interfaz para el método de fabricación
de iteradores, es decir, para la creación de un objeto iterador de la otra
jerarquía.
o Agregado Concreto (ConcreteAggregate): Implementa la estructura de
datos. Implementa el método de fabricación de iteradotes que crea un
iterador específico para su estructura.
• Colaboraciones entre participantes: Un iterador concreto mantiene la posición
actual dentro de la estructura de datos e interactúa con ésta para calcular el
siguiente elemento en el recorrido.
• Consecuencias:
o Distintos tipos de recorrido.
o Simplificación de la interfaz del agregado.
o Más de un recorrido simultáneo.
• Implementación:
o Control de la iteración: iterador externo vs. iterador interno.
o Definición del recorrido.
o Robustez del iterador ante cambios en la estructura.
o Operaciones adicionales en el iterador.
o Iteradores pueden necesitar acceso privilegiado.
o Iteradores para Composición.
o Iteradores nulos.
Patrón Template Method o Plantilla
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Define el esqueleto de un algoritmo en una operación, pero difiere
algunos pasos a las subclases, debido a que existen partes del algoritmo que
dependen de la especialización. Estas partes se implementarán en las subclases.
Patrones de diseño Máster en Bases de Datos e Internet
-93-
• Motivación:
o Framework para aplicaciones que permiten presentar múltiples
documentos al usuario (abstracciones Aplicación y Documento).
o Para una aplicación específica, se especializan los conceptos de
Aplicación y Documento.
o Problema: La abstracción aplicación conoce la operación genérica a
realizar (por ejemplo, abrir un documento), pero parte de la operación
depende del documento concreto.
o Solución: Implementar un método que difiera en otros métodos
abstractos las partes del algoritmo que no se conocen o que son
específicas.
o Un método plantilla es un método que define un algoritmo en base a una
serie de operaciones abstractas que son redefinidas por las. Subclases
para obtener un comportamiento concreto. Es decir, hay operaciones
genéricas comunes a todas las subclases en las que parte de su
funcionamiento no se conoce a nivel de las clases genéricas.
• Aplicabilidad:
o Implementar las partes invariables de un algoritmo una única vez y
permitir que las subclases definan el comportamiento que cambia (visión
top-down).
o Factorización de comportamiento común de las subclases en la
superclase, evitando la replicación de código mediante generalización
(visión botton-up).
Patrones de diseño Máster en Bases de Datos e Internet
-94-
o Para controlar la extensiones de las subclases. El método plantilla utiliza
métodos especiales (hooks) que son los únicos puntos que pueden ser
redefinidos en las subclases. Los métodos esqueleto no se deben redefinir
en las subclases por ello en Java se indican como métodos finales (final).
• Estructura:
• Participantes:
o Clase Abstracta (AbstractClass): Define operaciones primitivas
(normalmente abstractas) que las subclases implementan. Implementa un
método plantilla que define el esqueleto de un algoritmo y que utiliza las
operaciones primitivas.
o Clase Concreta (ConcreteClass): Implementa las operaciones
primitivas que definen el comportamiento específico del algoritmo para
las subclases.
• Colaboraciones entre participantes: Las clases concretas confían en la clase
abstracta la responsabilidad de la parte invariable del algoritmo, mientras que la
parte variable es responsabilidad de cada una de las subclases.
• Consecuencias:
o Fundamental para la reutilización de código, puesto que evita la
repetición del código genérico facilitando el posterior mantenimiento de
este.
o Invierte el control: la superclase es la encargada de llamar a las
operaciones definidas en las subclases.
Patrones de diseño Máster en Bases de Datos e Internet
-95-
o Distinción entre:
Operación primitiva definida en la superclase normalmente como
abstracta para obligar a cada una de las subclases a
implementarla.
Operaciones de enganche (Hooks) proporcionan código por
defecto en la superclase (quizá el comportamiento por defecto, el
cual puede ser no hacer nada) que puede ser refinado en las
subclases si es necesario.
Patrón Visitor o Visitante
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Permite definir una operación sobre objetos de una jerarquía de
clases sin modificar las clases sobre las que opera.
• Motivación:
o Compilador que representa programas como árboles con su sintaxis
abstracta.
o Necesarias diversas operaciones sobre el árbol sintáctico: Comprobación
de tipos, optimización de código, reestructuración de código, generación
de código, instrumentación...
o Cada nodo en el árbol sintáctico necesita un tratamiento diferente: clases.
Patrones de diseño Máster en Bases de Datos e Internet
-96-
o Problema: Difícil de entender, mantener, modificar y extender puesto
que cada clase (variable, asignación,...) tiene su parte correspondiente de
cada una de las operaciones.
o Solución: Agrupar las operaciones relacionadas de cada clase en un
objeto (visitante) y pasarlo como argumento a los elementos del árbol
sintáctico. El elemento “acepta” al visitante enviándole una petición
específica para su clase con él mismo como argumento:
VariableRef → VisitVariableRef
Assignment → VisitAssignment
o Para permitir más de un visitante, se define una superclase abstracta con
una operación por cada tipo de nodo (dos jerarquías!).
• Aplicabilidad:
o Varias clases de objetos con interfaces diferentes y se desean realizar
operaciones que dependen de sus clases concretas.
Patrones de diseño Máster en Bases de Datos e Internet
-97-
o Se necesitan diversas operaciones (no siempre relacionadas) sobre
objetos de una jerarquía y no se desea recargar las clases con estas
operaciones:
Agrupa operaciones relacionadas en una clase.
Si la jerarquía se usa en diversas aplicaciones, sólo se incluyen
las operaciones relevantes.
o Las clases de la jerarquía no cambian, pero se añaden con frecuencia
operaciones a la estructura. Si la jerarquía cambia, NO es aplicable.
• Estructura:
• Participantes:
o Visitante (Visitor): Declara una operación de visita para cada elemento
concreto en la estructura de objetos, que incluye el propio objeto
visitado.
o Visitante Concreto (ConcreteVisitor): Implementa las operaciones del
visitante y acumula resultados como estado local.
o Elemento (Element): Define una operación “Accept” que toma un
visitante como argumento.
o Elemento Concreto (ConcreteElement): Implementa la operación
“Accept”.
Patrones de diseño Máster en Bases de Datos e Internet
-98-
• Colaboraciones entre participantes:
o El cliente debe crear un visitante concreto y luego visitar cada elemento
de la estructura de objetos con dicho visitante.
o Cuando se visita un elemento, éste llama a la operación del visitante
correspondiente a su clase.
o Normalmente, el objeto se pasa como argumento para permitir al
visitante el acceso a su estado.
• Consecuencias:
o Añadir operaciones nuevas es sencillo.
o Agrupa operaciones relacionadas y separa las no relacionadas.
o Difícil añadir nuevas clases de elementos.
o No tiene que limitarse a una única jerarquía de elementos.
o Facilita la acumulación de estado.
o Problemas con la encapsulación.
Patrón Command o Comando
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Encapsula una petición como un objeto. Permite la parametrizaci´on
de clientes con diferentes peticiones, crear colas de peticiones y soporte de
operaciones cancelables (undo).
• Motivación:
o En ocasiones es necesario realizar peticiones sin:
Patrones de diseño Máster en Bases de Datos e Internet
-99-
Conocer información acerca de la operación a realizar.
Conocer información acerca del receptor de la petición.
o Ejemplo: Herramientas para la creación de interfaces de usuario:
Botones y opciones de menú ejecutan una petición, pero esa
petición depende de la aplicación.
o Solución: Convertir la petición en un objeto.
o Clave: Clase abstracta que declara la interfaz para la ejecución de
operaciones.
o Las subclases concretas de Command especifican el par receptor-acción:
Atributo que almacena referencia al receptor.
Comportamiento de la clase define la acción.
o Comando Pegar:
o Comando Abrir:
Patrones de diseño Máster en Bases de Datos e Internet
-100-
o Macrocomando: composición de comandos:
o Fundamental: Separación del objeto que desencadena la operación del
objeto que conoce como llevarla a cabo:
Compartición de comandos por diferentes elementos.
Cambio dinámico de comandos (sensible al contexto)
Composición de comandos (scripting)
• Aplicabilidad:
o Establecer como parámetro de un objeto la acción a realizar (visión OO
de un callback)
o Especificar, encolar, y ejecutar peticiones en diferentes momentos
o Soporte de Deshacer
El comando almacena estado para invertir su efecto
Añadir método Unexecute a la interfaz del comando
Comandos ejecutados se guardan en una lista histórica
Patrones de diseño Máster en Bases de Datos e Internet
-101-
Undo-Redo → recorrer la lista adelante y atrás llamando a
Unexecute y Execute respectivamente
o Soporte de Logging
Aumentando la interfaz del comando con operaciones de salvar-
guardar (log persistente de cambios)
Recuperación: cargar los comandos guardados e invocar su
Execute en secuencia
o Soporte de Transacciones
• Estructura:
• Participantes:
o Comando (Command): Declara la interfaz para ejecutar una operación.
o Comando Concreto (ConcreteCommand): Define un vínculo entre un
objeto receptor y una acción. Implementa la interfaz Comando,
invocando la operación sobre el receptor
o Cliente (Client): Crea un Comando Concreto y establece su receptor
o Invocador (Invoker): Solicita al comando que ejecute su acción
o Receptor (Receiver): Conoce cómo realizar las operaciones asociadas
con la ejecución de un comando
• Colaboraciones entre participantes:
o Cliente crea Comando Concreto y especifica su receptor.
o El invocador envía el mensaje Execute a un comando.
o El Comando Concreto almacena el estado necesario para deshacer.
Patrones de diseño Máster en Bases de Datos e Internet
-102-
o El Comando Concreto invoca las operaciones sobre el receptor para
realizar la petición.
• Consecuencias:
o Desacoplamiento del objeto que invoca la operación del objeto que
conoce como llevarla a cabo.
o Comandos pueden ser manipulados y extendidos como cualquier objeto.
o Composición de comandos.
o Fácil añadir comandos: no es necesario modificar clases existentes.
• Implementación:
o Responsabilidad asignada al comando.
o Soporte de Undo/Redo.
o Evitar acumulación de errores en el proceso de deshacer.
Patrón Memento o Recuerdo
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Permite capturar y extraer el estado interno de un objeto, sin violar
su encapsulación, de tal modo que se puede restaurar su estado a posteriori.
• Motivación: Operaciones de deshacer, transacciones...
• Aplicabilidad:
o Cuando se dan las dos siguientes condiciones:
Una imagen del estado del objeto (o un subconjunto) debe ser
almacenado de tal forma que pueda ser restaurado más tarde.
Patrones de diseño Máster en Bases de Datos e Internet
-103-
Una interfaz directa para obtener el estado expondría detalles de
implementación, violando la encapsulación del objeto.
• Estructura:
• Participantes:
o Recuerdo (Memento): Almacena el estado interno de la clase
Originante. Sólo permite el acceso al estado almacenado a la clase
Originante.
o Originante (Originator): Crea un Recuerdo con la imagen de su estado
actual. Usa un Recuerdo para restaurar su estado interno.
o Cuidador (Caretaker): Responsable de almacenar los Recuerdos. No
opera o examina el contenido de los Recuerdos.
• Colaboraciones entre participantes:
o El cuidador solicita un recuerdo del originante, lo almacena por un
tiempo, y si es necesario, lo devuelve al originante
o Los recuerdos son pasivos
Patrones de diseño Máster en Bases de Datos e Internet
-104-
• Consecuencias:
o Evita la exposición de información que sólo debe gestionar el originante,
pero que debe guardarse fuera de éste.
o Simplifica el originante, al separar la gestión de los recuerdos.
o Puede resultar costoso.
o Difícil en algunos lenguajes el soporte de dos visibilidades distintas.
o Oculta el coste de almacenamiento del recuerdo.
• Implementación:
o Soporte de dos visibilidades diferentes
o Almacenamiento de cambios incrementales
Particularmente útil en la implementación de operación deshacer
dado que se conoce la secuencia de cambios realizados (histórico)
Patrón Mediator o Mediador
• Clasificación: De comportamiento porque determina como se debe realizar el
intercambio de mensajes entre los diferentes objetos para resolver una tarea.
• Propósito: Define un objeto que encapsula la interacción entre varios objetos
independientes.
• Motivación:
o OO distribuye comportamiento/responsabilidad entre objetos:
Estructura de objetos con múltiples conexiones
Caso extremo: objetos totalmente conexos
o Consecuencia: pérdida de independencia reduce reusabilidad:
El sistema actúa de forma monolítica: para reusar un componente
se necesitan aquellos de los que depende
Difícil cambiar el comportamiento al estar repartido entre
muchos objetos
o Ejemplo: Ventanas de diálogo
Patrones de diseño Máster en Bases de Datos e Internet
-105-
o Existen dependencias entre los componentes:
Selecciones realizadas sobre unos componentes pueden modificar
el estado de otros componentes.
o Diferentes diálogos tienen diferentes dependencias entre los
componentes:
Necesario extender clases existentes para implementar el
comportamiento específico (tedioso, no reutilizable)
o Solución: Encapsular el comportamiento colectivo en un objeto
mediador:
Responsable de controlar y coordinar la interacción.
Intermediario que evita el conocimiento directo entre los objetos
(los objetos sólo conocen al coordinador)
Patrones de diseño Máster en Bases de Datos e Internet
-106-
o El coordinador media entre la lista de selección y el campo de edición:
Lista de selección cambio al mediador.
Mediador consultaba el valor actual de la lista.
Mediador solicita al campo de edición que cambie.
• Aplicabilidad:
Patrones de diseño Máster en Bases de Datos e Internet
-107-
o Un conjunto de objetos se comunican de manera compleja, siendo sus
interdependencias difíciles de entender.
o Es difícil reusar un objeto porque hace referencia y se comunica con
otros objetos.
o El comportamiento de un conjunto de objetos debe ser personalizable sin
necesidad de extender muchas clases.
• Estructura:
• Participantes:
o Mediador (Mediator): Define la interfaz para la comunicaci´on con los
objetos coordinados.
o Mediador Concreto (ConcreteMediator): Implementa el
comportamiento cooperativo. Conoce y mantiene a los objetos
coordinados.
o Clases coordinadas (Colleague classes): Cada clase coordinada conoce
a su mediador. Un objeto de la clase coordinada se comunica con su
Patrones de diseño Máster en Bases de Datos e Internet
-108-
mediador en lugar de hacerlo directamente con los restantes objetos
coordinados.
• Colaboraciones entre participantes:
o Sólo hay comunicación coordinado – mediador.
o El mediador implementa la coordinación redirigiendo los mensajes a los
objetos apropiados.
• Consecuencias:
o Reduce las extensiones de clases existentes.
o Desacopla objetos coordinados.
o Simplifica protocolo entre objetos.
o Abstrae la forma de cooperación de los objetos.
o Centraliza el control.
• Implementación:
o Omisión de la clase abstracta Mediador.
o Comunicación medidor – objetos coordinados:
Patrón Observador.
Interfaz de notificación específico.
o Soporte de Observadores complejos.
Patrones de diseño Máster en Bases de Datos e Internet
-109-
Patrones de diseño Máster en Bases de Datos e Internet
-110-
BIBLIOGRAFÍA Y REFERENCIAS
E. Gamma, R. Helm, R. Johnson, J. Vlissides. Design Patterns. Elements of Reusable
Object-Oriented Software. Addison-Wesley Professional Computing Series, 1995.
ISBN: 0-201-63361-2.
Sitio Web del libro anterior http://hillside.net/patterns/DPBook/DPBook.html [Ultimo
acceso 10 de febrero de 2010].
Larman, Craig. UML y patrones. Segunda Edición. Prentice Hall. 2002.
Sitio Web de Víctor Gulías http://www.fi.udc.es/~gulias [Último acceso 20 de enero de
2009]
M. Fowler, K. Scott. UML Distilled. Addison-Wesley Longman, 1997.
G. Booch, I. Jacobson, J. Rumbaugh. El Lenguaje Unificado de Modelado. Guía del
usuario. Addison-Wesley,1999.
J. Rumbaugh, I. Jacobson, G. Booch, El Lenguaje Unificado de Modelado. Manual de
referencia. Addison-Wesley, 2000.
K. Arnold, J. Gosling. The Java Programming Language. The Java Series, Addison-
Wesley, 1998.
Herbert Schilt. Java 2. Manual de Referencia. McGraw-Hill, 2001. ISBN: 8448131738.