Professional Documents
Culture Documents
Orientada a Objetos
PATRONES DE DISEÑO
Patrones y Frameworks
Creación:
Se preocupan del proceso de creación de un objeto
Estructurales: Comportamiento:
Se preocupan de como las propósito Se preocupan con los
clases y objetos se componen algoritmos y la asignación
para formar estructuras de responsabilidades
mas grandes. entre los objetos
10
Patrones de Diseño de
Comportamiento
• Un nombre
• El problema que intenta resolver
– Incluye las condiciones para que el patrón sea aplicable
• La solución al problema brindada por el patrón
– Los elementos (clases objetos) involucrados, sus roles,
responsabilidades, relaciones y colaboraciones
– No un diseño o implementación concreta
• Las consecuencias de aplicar el patrón
– Compromiso entre tiempo y espacio
– Problemas de implementación y lenguajes
– Efectos en la flexibilidad, extensibilidad, portabilidad
13
El Patrón Observer: El Problema
14
15
Participantes del Patrón Observador
18
19
20
Las Consecuencias del Patrón
Observador
• + Aparejamiento abstracto y mínimo entre el Sujeto y el
Observador: El sujeto no conoce la clase concreta del
observador, las clases sujetoconcreto y
observadorconcreto pueden ser reusadas
independientemente, los sujetos y observadores
pueden incluso pertenecer a diferentes capas de
abstracción del sistema
• + Soporte para comunicación broadcast: la notificación
enviada por el sujeto no necesita especificar un
receptor, se transmitirá a todos las partes interesadas
(subscritas)
• - Actualizaciones no esperadas: los observadores no
tienen conocimiento de la existencia de los demás, una
pequeña operación pueda causar una cascada de
actualizaciones innecesarias. 21
La implementación del patrón
Observador (1)
• Mapear los sujetos a sus observadores: El sujeto mantiene
referencias explícitas a los observadores a los que debe
notificar o una tabla de búsqueda es instalada; hay un
compromiso entre tiempo y memoria.
• Observar a más de un sujeto: pude ser necesario en
algunas situaciones; la interface actualizar debe ser
extendida para llevar registro del sujeto que esta enviando
el mensaje de actualización, permitiendo al observador
saber que sujeto debe examinar.
• Quien dispara los cambios (quien llam a notificar):
– Todas las operaciones en el sujeto llaman a notificar luego de
cambiar el estado del sujeto. Operaciones consecutivas pueden
causar actualizaciones consecutivas que pueden no ser necesarias
y no es eficiente
– Hacer llamadas a notificar es responsabilidad del cliente; esto es
propenso a error 22
La implementación del patrón
Observador (2)
• Las referencias colgantes a sujetos borrados: borrar un
sujeto no debe producir referencias colgantes en sus
observadores; solamente borrar el observador no es
tampoco, frecuentemente, una buena idea. Cuando se
borra un Sujeto los Observadores deben ser notificados
de tal manera que puedan resetear sus referencias al
Sujeto.
• Asegurarse que el Sujeto es consistente antes de llamar
a notificar: los observadores preguntarán el nuevo estado
del sujeto en su actualización; esta regla es fácilmente
violada sin intención cuando la subclases de Sujeto
llaman a operaciones heredadas
• Especificar modificaciones de interés de manera explícita:
la eficiencia en la actualización puede ser mejorada
cuando los observadores se registran por eventos de
interés solamente 23
La implementación del patrón
Observador (2)
• Evitar protocolos de actualización propios del observador,
los modelos pull y push:
– En el modelo push, el sujeto envía a sus observadores información
detallada en que ha cambiado; la clase sujeto hace la asunción
acerca de las necesidades del Observador.
– En el modelo pull el Sujeto envía nada más que la información
mínima de notificación y el Observador pregunta por los detalles de
manera explícita; esto hace énfasis en la ignorancia del Sujeto de
sus Observadores; puede ser ineficiente porque los Observadores
deben acceder lo que ha cambiado sin ayuda.
• Encapsula actualizaciones semánticamente complejas:
instala un administrador explícito de cambio que maneja la
relación Sujeto-Observador y define una estrategia
particular de actualización
24
25
El Patrón Composite: El Problema
Compone objetos en estructuras de árbol para
representar jerarquías parte-todo y deja que los
clientes traten a los objetos individuales y
composiciones de manera uniforme
32
Las consecuencias del Patrón
Composición
• + Hace al cliente más simple: los clientes pueden tratar
a las estructuras compuestas y a los individuos de
manera uniforme, los clientes normalmente no
necesitan saber y no les debería importar si están
tratando con una hoja o una composición.
• + Hace más fácil añadir un nuevo tipo de componentes:
el código del cliente trabaja automáticamente con las
composiciones u hojas recién definidas
• - Puede volver al diseño muy general: la desventaja de
hacer sencillo el añadir nuevos componentes es que
eso dificulta restringir los componentes de una
composición, algunas veces en la composición se
desea solo cierto tipo de hijos. Con el patrón
Composición no se pude confiar en que el sistema hará
cumplir esto. 33
La implementación del Patrón
Composición (1)
• Referencias explícitas al padre: simplifica el recorrido y manejo
de estructuras compuestas; son definidas mejor en la clase
Componente; es esencial para mantener la invariabilidad de que
todos los hijos de una composición tienen como padre a una
composición que a su vez los tiene como hijos.
• Compartición de componentes: puede ser útil por ejemplo para
reducir los requerimientos de almacenamiento, pero puede
llevar a ambigüedades cuando se requiera recorrer la estructura
hacia arriba.
• Maximizar la interface del componente: para lograr que los
clientes no conozcan la clase de hoja o composición que estan
usando., la clase componente debería definir tantas
operaciones comunes en las clases Hoja y Composición como
sea posible; esto entra en conflicto con el diseño de la jerarquía
de clases que dice que una clase solo debe implementar las
operaciones que tienen sentido en todas sus subclases. Se
requiere cierta creatividad para encontrar buenas
implementaciones por defecto ( ej. Hijos (hoja) = {}) 34
La implementación del Patrón
Composición (2)
• El acceso a los hijos y el manejo de operaciones: definir la
interfaz para el manejo de los hijos a nivel del componente
da transparencia pero afecta la seguridad, los clientes
pueden hacer cosas sin sentido tales como añadir o borrar
una hoja, esto debe capturarse en una implementación
estándar: no hacer nada o arrojar un error
• Las variables de instancia mantienen a los hijos:
comúnmente estas variables de instancia pertenecen donde
las operaciones de acceso y manejo están, pero cuando
están en la clase componente, se tiene un penalidad de
espacio, ya que las Hojas nunca tienen hijos.
• Borrar componentes: en los lenguajes sin recolección de
basura es mejor hacer a la Composición de borrar a sus
hijos: una excepción es cuando una objeto hoja es
compartido. 35
La implementación del Patrón
Composición (3)
• La estructura de datos para guarda hijos: una variedad de
estructuras de datos están disponibles: listas, árboles,
arreglos, tablas has; la elección depende en la eficiencia;
alternativamente cada hijo puede ser guardado en una
variable de instancia separada; todas las operaciones de
acceso y manejo deben entonces ser implementadas en
cada subclase composición.
• Ordenamiento de hijos: cuando el orden de los hijos es un
problema, la interfaz de acceso y manejo de los hijos debe
estar diseñada cuidadosamente para manipular esta
secuencia
• Caching: cuando la composición necesita ser recorrida o
buscada frecuentemente la clase composición puede hacer
caching de la información de sus hijos; los cambios a un
componente requiere invalidad los caches de su padre. 36
El patrón Singleton: El Problema
37
Participación y Colaboración en
el Patrón Singleton
Participante:
• Singleton:
– Es responsable por crear y almacenar su propia
instancia única.
– Define una operación Instancia que permite al los
clientes acceder su única instancia
Colaboración
– La operación Instancia a nivel de clase retorna o
crea una sola instancia; un atributo a nivel de clase
contiene un valor por defecto indicando que no hay
una instancia todavía o una sola instancia
38
39
Consecuencias del Patrón
Singleton
• + Acceso controlado a una sola instancia: debido a que el
Singleton encapsula su sola instancia, tiene control estricto
sobre ella.
• + Reduce el espacio de nombres: es una mejora a polucionar
el espacio de nombres con variables globales que contendrán
instancias únicas
• + Permite refinamiento de operaciones y representación: la
clase Singleton puede tener subclases y la aplicación pude ser
configurada con una instancia de la clases necesitada en
tiempo de ejecución
• + Permite un número variable de instancias: el mismo
acercamiento puede ser usado para controlar el número de
instancias que existen; una operación que de acceso a la
instancia debe ser proveída
• + Mas flexible que usar una clase con operaciones solamente. 40
La Implementación del Patrón
Singleton
• Asegurar una única instancia:
– El constructor o operación new debe estar protegida o
sobrescrita para evita que se creen otras instancias
accidentalmente por código del usuario.
• Subclases de la clase Singleton:
– El principal problema es instalar una única instancia de
un tipo deseado en tiempo de ejecución
– Cuando todas las subclases son conocidas de antemano
la operación Instancia puede ser un condicional y crear la
instancia correcta dependiendo de algún parámetro y
alimentación del usuario
– Cuando las subclases no son conocidas de antemano un
registro puede ser usado: todas las subclases se
registran antes de instanciarse; la operación Instancia
escoge la instancia correcta dependiendo de esto. 41
El patrón Abstract Factory: El
Problema
Provee una interfaz para crear familias de objetos
relacionados o dependientes sin especificar su clase
concreta
-Un toolkit GUI que
soporta múltiples
visualizaciones
- Lograr portabilidad a
través de
aplicaciones en
diferentes sistemas
También llamada: Kit de ventanas
42
43
Los participantes del Patrón de
Fábrica Abstracta
• AbstractFactory: declara una interfase para
operaciones que crean objetos de productos
abstractos
• ConcreteFactory: implementa las operaciones para
crear objetos de productos concretos
• AbstractProduct: declara una interfase para un tipo
de objeto producto
• ConcreteProduct: define un objeto producto a ser creado
por su correspondiente fábrica; implementa la interfase
AbstractProduct
• Cliente: usa sola interfaces declaradas por AbstractProduct
y AbstractFactory 44
45
46
Colaboración en el Patrón de
Fábrica Abstracta
47
Consecuencias del Patrón
Fábrica Abstracta (1)
• + Clases concretas aisladas: la AbstractFactory
encapsula la responsabilidad y el proceso de crear
objetos producto, aísla al cliente de las clases con
implementación; los clientes manipulan las instancias a
través de sus interfaces abstractas; los nombres de las
clases producto no aparecen en el código cliente.
• + Hace fácil el intercambio de familias de
productos: la clase ConcreteFactory aparece
solamente una vez en la aplicación, esto es, donde es
instanciada, así que es fácil de remplazar; dado que la
fábrica abstracta crea una familia entera de productos,
la familia completa pude cambiar de manera sencilla
48
Consecuencias del Patrón
Fábrica Abstracta (2)
• + Promueve la consistencia entre productos: cuando
los productos en una familia son diseñados para
trabajar juntos, es importante para la aplicación el usar
los objeto de una sola familia; el patrón de fábrica
abstracta hace fácil cumplir esto.
• +- Soportar nuevos tipos de productos es difícil:
extender las fábricas abstractas para producir una
nueva clase de producto no es fácil porque el conjunto
de los produtos que pueden ser creados es fija en la
interface AbstractFactory; soportar nuevas clases de
productos requiere extender la interfase lo que
involucra cambiar la clase AbstractFactory y todas sus
subclases
49
Implentación del Patrón Fábrica
Abstracta (1)
• Las fábricas son singletons: una aplicación necesita
solamente una instancia de una fábrica concreta por
familia de productos, así que es mejor implementarla
como un singleton
• Creando nuevos productos:
– AbstractFactory solo declara una interfaz para crear productos,
le corresponde a las subclases de ConcreteFactory crear
verdaderamente los productos
– La forma más común de hacer esto es usar un método-fábrica
para cada producto; cada fábrica concreta especifica su
producto al sobrescribir cada método-fábrica; es simple pero
requiere una nueva fábrica concreta para cada producto en la
familia, aun si solo difieren levemente.
– Una alternativa es implementar las fábricas concretas con el
patrón prototipo; la fábrica concreta es inicializada con una
instancia prototípica de cada producto y crea nuevos
productos por clonación
50
Implentación del Patrón Fábrica
Abstracta (2)
• Definir fábricas extensibles:
– Un diseño más flexible pero menos seguro es proveer
una fábrica abstracta con un función “hacer” que tome
como parámetro el tipo de objeto a crear (como
cadena o identificador de clase)
– Es más fácil de realizar en un lenguaje dinámico que
en uno estático por el tipo retornado por esta
operación “hacer”
– Puede ser usado en C++ solo si todos los objetos
productos tienen una clase base común o si los objeto
productos pueden ser coercionados en el tipo que el
cliente que pida el producto requiera. En este último
los productos retornados tienen todos la misma
interfaz abstracta y el cliente no podra diferenciar o
hacer asunciones acerca de la clase del producto 51
El Patrón Factory Method: El
Problema
Define una interfaz para crear un objeto pero deja
que las subclases decidan que objeto instanciar
- Cuando frameworks o
toolkits uan clases
abstractas para definir
y manter relaciones
entre objetos y son
responsables de crear
también los objetos
52
53
54
Participantes y Colaboración en
el Patrón de la Método Fábrica
• Producto: define la interfase de los objetos que el método
fábrica crea
• ProductoConcreto: implementa la interfase Producto
• Creador
– Declara el método fábrica, que retorna un objeto tipo Producto;
pude definir una implementación por defecto
– Puede llamar al método fábrica para crear objetos Producto
• CreadorConcreto: sobrescribe el método fábrica para devolver una
instancia de ProductoConcreto
60
61
62
Consecuencias del Patrón
Prototipo (1)
• + Esconde del cliente las clases concretas del productos: El
cliente puede trabajar con las clases específicas de la aplicación
sin necesidad de modificarlas.
• + Los productos pueden ser añadidos y removidos en tiempo de
ejecución: nuevos productos concretos pueden ser incorporados
solo registrándolos con el cliente
• + Especificar nuevos objetos por valores cambiantes: nuevas
clases de objetos pueden ser efectivamente definidos al instanciar
una clase específica, llenar algunas de sus variables de instancia
y registrarla como un prototipo
• + Especificar nuevos objetos por una estructura variante:
estructuras complejas definidas por el usuario pueden ser
registradas como prototipos también y ser usads una y otra vez al
clonarlas 63
Consecuencias del Patrón
Prototipo (2)
• + Reduce las subclases: al contrario que el Método Fábrica, que a
menudo produce una jerarquía de clase creadora que asemeja al
jerarquía de ProductosConcretos
• + Configura una aplicación con clases dinámicamente: cuando el
ambiente de tiempo de ejecución soporta carga dinámica de
clases, el patrón de prototipo es una llave para explotar esas
facilidades en un lenguaje estático (los constructores de las
clases cargadas dinámicamente no pueden ser accesadas de
manera estática; en vez de esto el ambiente de tiempo de
ejecución crea automáticamente una instancia del prototipo que la
aplicación puede usar a través del manejador de prototipos)
• - Implementar la operación Clonar: es difícil cuando las clases en
construcción existen o cuando internamente se incluye objetos
que no soportan la copia o tiene referencias circulares
64
Implementación del Patrón
Prototipo
• Usar un manejador de prototipos: cuando el número de
prototipos en un sistema no es fijo, es mejor usar un registro
de los prototipos existentes
• Implementar la operación clonación: muchos lenguajes dan
soporte a la implementación del operador clonación
(constructores de copia en C++, método copy en Smalltalk,
guardar + cargar en sistemas que lo soportan) pero en si
mismos no solucionan el problema de la copia superficial /
profunda
• Inicializar clones: algunos clientes son felices con el clone
como esta, otros desean inicializarlo; pasando parámetros a
la operación clonar elimina la uniformidad de la interfase.
Hay que utilizar las operaciones de cambio de estado luego
de la clonación o proveer un método Inicializar
• En lenguajes que tratan a las clases como objetos de primera
clase, el objeto clase en si mismo es como el prototipo para
crear instancias de cada clase 65
El Patrón Builder Pattern: El
Problema
66
67
Participantes del Patrón
Constructor
68
69
Colaboración en el Patrón
Constructor
• El cliente crea al objeto Director y lo configura
con el objeto Constructor deseado.
• El Director notifica al constructor que parte del
producto debe ser construida
• El constructor maneja los requerimientos del
director y añada partes al producto
• El cliente recupera el producto del constructor
70
71
Consecuencias del Patrón
Constructor
• + Permite variar la representación interna del producto:
los directores usan la interfaz abstracta provista por el
constructor para construir el producto; para cambiar la
representación del producto, solo se debe hacer un
nuevo tipo de constructor.
• + Permite el reuso de los Constructores Concretos:
todo el código para la construcción y representación
esta encapsulado; diferentes directores usan el mismo
Constructor Concreto
• + Da un control más fino sobre el proceso de
construcción: En otros patrones creacionales, la
construcción se realiza en un solo paso; aquí el
producto es construido paso a paso y bajo la guía del
director dando un control más fino sobre la estructura
interna del producto resultante 72
Implementación del Patrón
Constructor
• Interfaces de Ensamblaje y Construcción:
– La interfaz del Constructor debe ser generalmente suficiente para
permitir la construcción de productos de toda clase de
Constructores Concretos
– El modelo para la construcción y ensamblaje es una decisión
importante del diseño
• ¿Por qué no clases abstractas para los productos?:
– En el caso común, los productos pueden diferir tanto en sus
representaciones que se gana muy poco dando a todos los
productos una clase padre común.
– Debido a que el cliente configura al Director con el Constructor
Concreto adecuado, el cliente conoce el producto resultante.
• Métodos vacíos como valor por defecto en el Constructor
– En C++ los métodos para construir son intencionalmente no
puramente virtuales sino métodos vacíos; esto permite al cliente
sobrescribir solamente las operaciones en las cual está interesado.
73
El Patrón Façade: El Problema
• Proxy:
– Mantiene una referencia que permite al proxy acceder al sujeto
real
– Provee una interfase idéntica a la del Sujeto de tal manera que el
proxy puede sustituir al objeto real
– Controla el acceso al sujeto real y puede ser responsable de su
creación y borrado.
– Los Proxies remotos son responsables por la codificación de un
requerimiento y sus argumentos y por enviar el requerimiento al
sujeto real en otro espacio de direcciones.
– Los proxies Virtuales pueden guardar información acerca del
sujeto real de tal manera que puede posponer el acceso a él.
– Los proxies de protección verifica que el que llama tiene acceso y
permiso para llevar a cabo la petición
84
85
Participantes y Colaboración del
Patrón Proxy (2)
• Sujeto:
– Define una interfaz común para el SujetoReal y Proxy,
de tal manera que el Proxy puede ser usado en
cualquier lugar donde se pida un SujetoReal
• SujetoReal
– Define el objeto real que el proxy representa
86
87
Consecuencias de Patrón Proxy
89
90
91
92
93
Aplicabilidad del Patrón
PesoMosca
• Flyweight
– Declara una interfase a través de la cual flyweights
pueden recibir y actuar según su estado extrínseco
• Concrete Flyweight
– Implementa la interfaz del flyweight y añade
almacenamiento para el estado intrínseco.
– Un objeto flyweight concreto debe ser compartible; Ej.
Dos estado debe ser intrínsico
• Unshared Concrete Flyweight
– No todos las subclases flyweights necesitan ser
compartidas, flyweight concretos no compartidos
pueden tener objetos flyweight concretos a algún nivel.
95
Participantes del Patrón
PesoMosca (2)
• Fábrica Flyweight
– Crea y maneja objetos flyweight
– Asegura que los flyweights son compartidos
adecuadamente; cuando un cliente pide un
flyweight la fábrica flyweight devuelve un objeto
existen de un repositorio o crea uno y lo añade
al repositorio
• Cliente
– Mantiene una referencia hacia el o los flyweights
– Calcula o guarda el estado extrínseco de los
flyweights
96
97
Colaboraciones del Patrón
PesoMosca
98
99
Consecuencias del Patrón
PesoMosca
• - Los Flyweights pueden introducir costos en tiempo de
ejecución asociados con la transferencia, búsqueda, y/o
cálculo del estado extrínseco.
• + El incremento de los costos de tiempo de ejecución son
compensados por ahorros de almacenamiento, el cual
decrece
– Tanto cuanto más flyweights son compartidos
– Tanto cuanto la cantidad de estado intrínseco sea considerable
– Tanto cuanto la cantidad de estado extrínseco es considerable pero
puede ser calculado.
• - El patrón flyweight se combina con el patrón composición
para construir un grafo con varios nodos hoja. Debido a la
compartición los nodos hojas no pueden guardar a su padre lo
cual ocasiona un impacto mayor en como los objetos de la
jerarquía se comunican. 100
Implementación del Patrón
PesoMosca
• Remover el estado extrínseco:
– Identificar el estado extrínseco y removerlo de los objetos
compartidos
– Remover el estado extrínseco no ayudará si hay tantas clase
de estados extrínsecos como objetos antes de compartir.
– Idealmente el estado extrínseco pude ser calculado desde un
objeto estructura separado con menos requerimientos de
memoria.
• Manejando objetos compartidos:
– Use un almacenaje asociativo con la fábrica flyweight para
dejar que los clientes encuentren un flyweight particular
– Una forma de cuenta de referencia o de colección de basura
es necesaria para recuperar el almacenamiento de los
flyweights cuando estos ya no se usen
– Cuando el número de flyweights es pequeño y fijo, considere
inicializar el repositorio y mantener a los flyweights
permanentemente
101
El Patrón Iterador: El Problema
102
103
Participantes y Colaboración del
Patrón Iterador
• Iterador
– Define una interfaz para acceder y recorrer elementos
• IteradorConcreto
– Implementa la interfaz iterador
– Mantiene la pista de la posición actual en el recorrido
del agregado.
• Agregado
– Define una interfase para definir un objeto Iterador
• AgregadoConcreto
– Implementa la interfaz de creación de un iterador para
retornar una instancia del propio IteradorConcreto
• Un IteradorConcreto mantiene la pista del objeto
actual en el agregado y puede calcular el
siguiente objeto en el recorrido.
104
105
106
Consecuencias del Patrón
Iterador
• + Soporta la variación en el recorrido de un agregado:
agregados complejos pueden ser recorridos de
diferentes maneras, los iteradores hacen fácil cambiar
el algoritmo de recorrido solamente usando una
instancia diferente de iterador.
• + Simplifica la interfaz del agregado: La interfaz
agregado no esta obstaculizada por el soporte de
varios tipos de recorrido.
• + Más de un recorrido puede estar pendiente en el
mismo agregado: un iterador mantiene registro de su
propio estado de recorrido, por lo tanto más de un
recorrido puede estar en progreso al mismo tiempo.
107
Implementación del Patrón
Iterador (1)
• ¿Quién controla el iterador? Un iterador interno tiene control
absoluto sobre la iteración completa, los clientes entregan una
operación a ser realizar y el iterador aplica esa operación a
cada uno de los elementos del agregado. Con un iterador
externo, el cliente controla la iteracción. Ej.: el cliente avanza
el recorrido al pedir el siguiente ítem explícitamente. Los
iteradores externos son más flexibles (comparar dos
coleccíones es practicamente imposible. Los iteradores
internos son más fáciles de usar pero son más débiles en
lenguajes que no soportan objetos como primera clase.
• ¿Quién define el algoritmo de recorrido? El iterador puede ser
responsable del algoritmo de recorrido en dicho caso es fácil
usar diferentes algoritmos de recorrido en el mismo agregado
y usar el mismo algoritmo en agregados diferentes. El
agregado en si mismo puede ser responsable de el algoritmo
de recorrido y el iterador solo guara el estado de la iteración
(cursor) 108
Implementación del Patrón
Iterador (2)
• ¿Cuan robusto es el iterador? Un iterador robusto asegura que la
inserción y remoción no interfieren con el recorrido (y lo hace si no
se copia el agregado). Los iteradores robustos pueden por
ejemplo ser implementados a través de registrar los iteradores
con el agregado y hacer que el agregado ajuste el estado interno
de los iteradores después de una inserción o borrado de
elementos.
• Iteradores Polimórficos en C++ tiene un costo, requieren que el
objeto iterador sea asociado dinámicamente por el método
fábrica. Por esto si no hay necesidad de polimorfismo use
iteradores concretos los cuales pueden ser alojados en la pila.
Los iteradores polimórficos tienen otro problema, deben ser
eliminados por el código cliente, lo cual es propenso a errores. El
patrón proxy ofrece una solución. Usar la pila para alojar el proxy
del iterador real, hacer que el proxy asegure eliminar el iterador al
borrarse, de tal manera que cuando el proxy se destruya, también
lo hace el objeto iterador.
109
Implementación del Patrón
Iterador (3)
• Los iteradores pueden tener privilegios de acceso: un iterador
pude ser visto como una extensión del agregado que lo crea.
El iterador y el agregado están fuertemente aparejados. En
C++ pueden ser hechos amigos de tal manera que el agregado
no tenga que definir operaciones con el solo propósito de hacer
el recorrido más eficiente. Añadir nuevos recorridos se vuelve
difícil debido a que la interfaz del agregado tiene que cambiar
para permitir que otra clase sea amiga.
• Iteradores Nulos: un iterador nulo es un iterador degenerado
que es útil para manejar condiciones de borde. Por definición
un Iterador Nulo es siempre hecho. El Iterador Nulo hace
recorrer árboles y otras estructuras recursivas más fácil. A
cada punto en el recorrido el nodo actual es preguntado por el
iterador de su hijo. Un elemento del agregado retorna un
iterador concreto, una hoja devuelve el Iterador nulo
110
El Patrón Visitor: El Problema
116
117
118
Consecuencias del Patrón
Visitante (1)
• + Hace añadir nuevas operaciones fácil: una nueva
operación es definida añadiendo un visitante (en
contraste, cuando se extiende la funcionalidad sobre
varias clases cada clase debe cambiar para definir una
nueva operación)
• + Reúne operaciones relacionadas y separa las no
relacionadas: comportamiento relacionado se localiza
en el visitante y no se dispersa sobre las clases que
definen el objeto estructura
• - Añadir nuevos ElementosConcretos es difícil: cada
nuevo ElementoConcreto da lugar a una nueva
operación abstracta en el Visitante y una
correspondiente implementación en cada
VisitanteConcreto
119
Consecuencias del Patrón
Visitante (2)
• + Permite visitante a través de jerarquía de clases: un iterador
puede también visitar elementos de una estructura de objetos
cuando los recorre y llama a las operaciones sobre ellos, pero
todos los elementos de la estructura de objetos necesitan tener un
padre común. Los Visitantes no tienen esta restricción
• + Acumulación de Estado: El visitante puede acumular estados al
proceder con el recorrido. Sin un visitante este estado debe ser
pasado como un parámetro extra a ser manejado en variables
globales
• - Rompe la encapsulación: El acercamiento del Visitante asume
que la interfaz del ElementoConcreto es lo suficientemente
poderosa como para permiter al visitante hacer su trabajo. Como
resultado el patrón muchas veces fuerza a proveer operaciones
públicas para acceder al estado interno del elemento lo cual
puede comprometer la encapsulación
120
Implementación del Patrón
Visitante
• Doble Despacho: un aspecto principal del visitante es el
doble despacho, el significado de una operación de
aceptación depende del visitante y del elemento. Los
lenguajes que soportan doble despacho (CLOS)
pueden hacer esto sin ningún patrón.
• ¿Quien es responsable por recorrer el objeto
estructura? La responsabilidad por recorrerlo pude
estar con:
– El objeto estructura
– El visitante: es recomendable cuando un recorrido complejo es
requerido (por ejemplo uno que dependa del resultado de la
operación), sino no es recomendable porque mucho del código
de recorrido debería ser duplicado en cada VisitanteConcreto
para cada agregado ElementoConcreto
– Un objeto iterador separado
121
El Patrón State: El Problema
• Contexto
– Define la interfase de interés para los clientes
– Mantiene una instancia de algún EstadoConcreto que
define el estado actual
• Estado
– Define una interfase para encapsular el
comportamiento asociado con un estado particular del
Contexto
• Subclases de EstadoConcreto
– Cada subclase implementa un comportamiento
asociado con el estado del Contexto
124
Colaboraciones del Patrón Estado
127
Implementación del Patrón
Estado (2)
• Alternativa basadas en una tabla
– Usar una tabla, mapear cada estado, cada posible entrada y el
estado siguiente
– Este acercamiento convierte el código del condicional en una
tabla de búsqueda y el cambio del criterio de transición es
hecho al cambiar los datos en la tabla en vez de cambiar el
código.
– Las desventajas son que (1) la tabla de búsqueda es menos
eficientes que una llamada a función (virtual) (2) la tabla
captura el estado y las transiciones pero necesita ser
aumentada para realizar cálculos arbitrarios en cada
transición.
• Usar herencia dinámica
– Los lenguajes que permiten cambiar la clase de un objeto en
tiempo de ejecución soportan el patrón estado directamente.
Solamente deje que el objeto cambie su clase cuando el
estado cambia y el comportamiento cambiará también.
128
El Patrón Strategy: El Problema
130
Participantes del Patrón Estrategia
• Estrategia
– Declara una interfaz común a todos los algoritmos
soportados
– Contexto usa esta interfaz para llamar a los algoritmos
definidos por EstrategiaConcreta
• Subclases de EstrategiaConcreta
– Cada subclase implementa el algoritmo usando la
interfase Estrategia
• Contexto
– Es configurado como un objeto EstrategiConcreta
– Pude definir una interfaz que permite a Estrategia
acceder sus datos 131
Colaboraciones en el Patrón
Estrategia
• Un contexto envía requerimientos de sus clientes
a Estrategia
• Estrategia y Contexto interactúan para
implementar el algoritmo escogido
– Un Contexto puede pasar todo los datos requeridos por
el algoritmo a Estrategia cuando se llama al algoritmo.
– Contexto puede pasarse a si mismo como un
argumento a las operaciones de Estrategia de tal
menara que estas puedan llamarlo de vuelta si el
Contexto es requerido.
• Los clientes usualmente crean y pasan un objeto
EstrategiaConcreta al Contexto; de ahí los clientes
interactúan con el Contexto exclusivamente 132
Consecuencias del Patrón
Estrategia (1)
• + Las Jerarquías de las clases Estrategia definen una
familia de algoritmos o comportamientos para reusar.
La herencia puede factorizar la funcionalidad común de
estos algoritmos.
• + Es alternativo a subclase, Ej. Usar la jerarquía de
clases de contexto para implementar las variaciones en
el comportamiento. El comportamiento no esta fijo en
contesto así que el algoritmo pude variar
independientemente de Contexto.
• + Es una alternativa a usar sentencias condicionales
para seleccionar el comportamiento deseado
• + Puede ofrecer una elección de implementaciones
para el mismo comportamiento (Ej. Compromisos
espacio tiempo)
133
Consecuencias del Patrón
Estrategia (2)
• - Clientes deben estar consientes de las diferentes Estrategias.
Los clientes deben entender las diferencias entre lo que se ofrece
y ser capaces de seleccionar el apropiado. Por lo tanto el patrón
debería solo ser usado cuando la variación en algoritmo
(implementación) es relevante para el cliente.
• - Existe algo de sobrecarga en la comunicación entre la
Estrategia y el Contexto. Estrategia define una interfase
(general). Muchas de los algoritmos más simples no necesitan
toda la información que se envía.
• - El número de objetos en las aplicaciones aumenta Algunas
veces la sobrecarga puede ser reducida cuando
EstrategiasConcretas puede ser implementado por objetos sin
estado que pueden ser compartidos (Ej. El patrón flyweight)
134