0% encontró este documento útil (0 votos)
200 vistas117 páginas

Guía de Patrones de Diseño OO

Este documento presenta una introducción a los patrones de diseño. Explica brevemente por qué son útiles, cuándo y dónde surgió el concepto, qué son los patrones de diseño y para qué sirven. A continuación, clasifica los patrones en creacionales, estructurales y de comportamiento e incluye un índice de los temas que serán tratados.

Cargado por

Adriel Avila
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
200 vistas117 páginas

Guía de Patrones de Diseño OO

Este documento presenta una introducción a los patrones de diseño. Explica brevemente por qué son útiles, cuándo y dónde surgió el concepto, qué son los patrones de diseño y para qué sirven. A continuación, clasifica los patrones en creacionales, estructurales y de comportamiento e incluye un índice de los temas que serán tratados.

Cargado por

Adriel Avila
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

19/1/2021 Patrones de Diseño

Patrones de Diseño
Universo Santa Tecla
[email protected]
Version 0.0.1 

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 1/117
19/1/2021 Patrones de Diseño

Índice
¿Por qué?
¿Cuándo? ¿Dónde? ¿Quién?
¿Qué?
¿Para qué?
¿Cómo?
Elementos
Elementos Esenciales
Problema
Solución
Consecuencias
Clasi cación
Patrones Creacionales
Abstract Factory
Builder
Factory Method
Prototype
Singleton
Patrones Estructurales
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Patrones de Comportamiento
Chain of Responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template Method
Visitor
Relaciones
Aplicación
Bibliografía
Ponente

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 2/117
19/1/2021 Patrones de Diseño

¿Por qué?
Problemas de Diseño el diseño es difícil y reutilizable es incluso más difícil

Encontrar objetos apropiados Cohesión

Relacionar Estructuras del Tiempo de Compilación y de Ejecución Acoplamiento

Determinar la granularidad de los objetos Tamaño

Especificar interfaces de objetos Abstracción

Especificar la Implementación de Objetos Implementación

Poner a funcionar los mecanismos de reutilización Reusabilidad por composición, herencia y/o
parametrización

Problemas de Rediseño el diseño debería ser específico para el problema actual pero
también en general para direccionar futuros problemas y
requisitos y, así, evitar rediseños o al menos minimizarlos

Crear un objeto especificando su clase explícitamente Acoplamiento

Dependencias de las representaciones o Acoplamiento


implementaciones de objetos

Dependencias de plataformas hardware o software Acoplamiento

Dependencias de operaciones concretas Acoplamiento

Dependencias algorítmicas Acoplamiento

Fuerte acoplamiento Acoplamiento

Añadir funcionalidad mediante herencia Principio Abierto/Cerrardo

Incapacidad para modificar las clases Principio Abierto/Cerrardo


convenientemente

Los expertos, en diseño Obtener un diseño reusable y flexible correctamente a la primera es difícil, sino
orientados a objetos o cualquier no imposible
ámbito/disciplina/…,
No resolver cada problema desde cero
comparten/sugieren/…
Conocimiento/Know How: Intentar reusar una buena solución varias veces modificándola cada vez

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 3/117
19/1/2021 Patrones de Diseño

¿Cuándo? ¿Dónde? ¿Quién?


En el área de la arquitectura de edificios y ciudades: Producto Software

1977. Christopher Alexander publica A Pattern


Language propone un primer catálogo de patrones

1979. Christopher Alexander publica The Timeless


Problema
Way of Building propone el concepto de patrón

En el área del desarrollo de software orientado a objetos


(comunidad de Smalltalk)
Problema Recurrente
1987. Ward Cunningham y Kent Beck publican Using
Pattern Languages for OO Programs en OOPSLA

1990. Erich Gamma, Richard Helm, Ralph Johnson y


John Vlissides (Gang of Four -GoF-, La Banda de los Problema de Diseño Problema de Rediseño

Cuatro) publican Design Patterns con un catálogo de 23


patrones de diseño

Ley del Cambio Continuo


¿Cómo lo hago? ¿Cómo lo re-hago?

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 4/117
19/1/2021 Patrones de Diseño

¿Qué?

“ Cada patron describe


problema el cual ocurre una
un Nuestras soluciones se expresan en
términos de objetos e interfaces en vez
“ Son la descripción de la
comunicación de objetos y
de paredes y puertas pero el núcleo de
y otra vez en nuestro entorno ambas clases de patrones es una
clases que son
y describe el núcleo de una solución a un problema en un contexto particularizados para
solución para el problema, de resolver un problema de
tal forma que se puede usar diseño general en un
esta solución un millón de contexto particular
veces sin hacerlo de la misma — Gamma et al
forma dos veces Design Patterns

— Alexander
A Pattern Language

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 5/117
19/1/2021 Patrones de Diseño

¿Para qué?
Registrar la experiencia en diseño Producto Software

de software orientado a objetos


como patrones de diseño de forma que
la gente pueda reusarlo CalidadSoftware

efectivamente.

Expresar técnicas probadas más


Efectividad
accesibles a los desarrolladores de
nuevos sistemas.

Ayudar a elegir entre las Eficacia Eficiencia Mantenibilidad

alternativas de diseño que hacen


un sistema reutilizable y a evitar
alternativas que comprometen la Reusabilidad Robustez Fluidez Flexibilidad

reutilización.

Conseguir un diseño correcto más


Reusabilidad del Código Reusabilidad del Diseño Modularidad

rápido.

Nombrar, explicar y evalúar


sistemáticamente diseños Problema Patrón de Diseño Bajo Acoplamiento Alta Cohesión Grano Fino

importantes y recurrentes en un
sistema orientado a objetos.
ProblemaRecurrente
Mejorar la documentación y
mantenimiento de los sistemas
existentes mediante el suministro Problema de Diseño Problema de Rediseño

de una especificación explícita de


las interacciones de clases y objetos
y su intención subyacente. Ley del Cambio Continuo
¿Cómo lo hago? ¿Cómo lo re-hago?

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 6/117
19/1/2021 Patrones de Diseño

¿Cómo?

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 7/117
19/1/2021 Patrones de Diseño

Elementos
Elementos Esenciales
Para la descripción general del patrón se proponen 13
Patrón
elementos agrupados en 4 elementos esenciales:

Nombre: Nombre y Sinónimo

Problema: Motivación, Intención y Aplicabilidad


Elemento de Patrón
Solución: Estructura, Participantes, Colaboraciones,
Implementación, Códigos de Ejemplo, Usos Conocidos y
Patrones Relacionados

Consecuencias: Consecuencias Nombre Problema Solución Consecuencia

Nombre

Patrón

Elemento de Patrón

Nombre Problema Solución Consecuencia

Nombre Sinónimo

Elemento Descripción Ejemplo

Nombre Una o dos palabras que transmiten la esencia del patrón (problema, solución y consecuencias) Singleton
permite:

Aumentar inmediatamente nuestro vocabulario de diseño, para comunicarnos con otros


colegas o nosotros mismos y en la propia documentación.

Diseñar a un nivel más alto de abstracción.

Pensar en diseños y comunicarlos con sus compromisos.

Sinónimos Otros nombres conocidos para el patrón, si los hubiere. -

Problema

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 8/117
19/1/2021 Patrones de Diseño

Patrón

Elemento de Patrón

Nombre Problema Solución Consecuencia

Problema Recurrente Motivación Intención Aplicabilidad

Problema de Diseño Problema de Rediseño

Elemento Descripción Ejemplo: Singleton

Motivación Contexto para Para algunas clases es importante compartir una única instancia en el sistema.
entender el Ejemplos:
problema de
aunque haya muchas impresoras en un sistema, debería haber una única cola de
diseño abstracto
impresión
(representar
algoritmos como debería haber un solo sistema de ficheros y un solo gestor de ventanas
objetos, un filtro digital tendría un único convertidor analógico/digital
estructura
un sistema de cuentas bancarias será dedicado para servir a una compañía
inflexible de
clases u objetos, Código global, sin objeto!!! Código
…) y cómo (https://github.com/miw-
resolver el upm/IWVG/tree/master/doo/src/main/java/designPatterns/patterns/singleton/v1/basic/notObject)

problema

Intención Describe qué Asegurar que una clase tenga una única instancia y proveer un punto de acceso global para
razón de ser y ésta
qué hace el
patrón de
diseño sobre el
problema que
aborda

Aplicabilidad Lista de Debe ser exactamente una única instancia de la clase y debe ser accesible a los clientes
condiciones de desde un punto de acceso bien conocido.
ejemplos de
Cuando la única instancia debería ser extensible por sub-clasificación y los clientes
diseños pobres
deberían ser capaces de usar la instancia extendida sin modificar su código
que se deben
cumplir para
que tenga
sentido aplicar
el patrón

Solución

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 9/117
19/1/2021 Patrones de Diseño

Patrón

Elemento de Patrón Nombre

Problema Solución Consecuencia

Estructura Participantes Colaboraciones Implementación Códgios de Ejemplo Usos Conocidos Patrones Relacionados

Elemento Descripción Ejemplo: Singleton

Estructura Diagrama de
Singleton
clases del patrón
Singleton instance
attribute
getInstance()
method()

Participantes Reparto de Singleton define una operación Instance que permite a los clientes acceder a su única
responsabilidades instancia.
entre las clases del
Instance es una operación de clase (miembro estático)
patrón
Singleton puede ser responsable de crear su propia instancia única

Colaboraciones Diagrama de Los clientes acceden a la instancia única a través de la operación Instance de Singleton
secuencia de los
objetos de las
clases del patrón

Implementación Pistas o técnicas, Garantizar una única instancia. Código


quizás específicas (https://github.com/miw-
de un lenguaje upm/IWVG/tree/master/doo/src/main/java/designPatterns/patterns/singleton/v2/basic)

estático (C++, Java, Garantizar varias instancias. Código


…) o dinámico (https://github.com/miw-
(Smalltalk, upm/IWVG/tree/master/doo/src/main/java/designPatterns/patterns/singleton/v3/multipleInstances)
Javascript, …) a Garantizar subclasificación. Código
tener en cuenta al (https://github.com/miw-
aplicar el patrón upm/IWVG/tree/master/doo/src/main/java/designPatterns/patterns/singleton/v7/subclassifing/java)

Código de Ejemplo de código class Printer {


JAVA

ejemplo que ilustra una


implementación private static Printer instance = null;

del patrón en public static getInstance() {


diversos lenguajes. if (Printer.instance == null){
Printer.instance = new Singleton();
}
return Printer.instance;
}

private attribute;

private Printer(){
// init
}

public method(){
// body
}
}

Usos conocidos Dos o más ejemplos ChangeSet int Smalltalk-80


de diferentes
Session and WidgetKit en InterViews
aplicaciones en
sistemas reales

Patrones Patrones de diseño Abstract Factory


relacionados estrechamente
Builder
relacionados por
diferencias o Prototype
posible
colaboración

Consecuencias

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 10/117
19/1/2021 Patrones de Diseño

Patrón

Elemento de Patrón Nombre

Extensibilidad Consecuencia Problema Solución

Elemento Descripción Ejemplo: Singleton

Consecuencia Ventajas y desventajas, Acceso controlado a una única instancia. Como la clase encapsula su
compromisos de única instancia, puede tener un control estricto sobre cómo y cuándo
espacio/tiempo, cuestiones del los clientes acceden a ésta.
lenguaje (estático) y de
Reducir el espacio de nombres. Es una mejora sobre las variables
ejecución (dinámico).
globales ya que se evita contaminar el espacio de nombres con las
Impacto en la reutilización, variables globales que almacenen las instancias únicas.
flexibilidad, extensibilidad o
Permite el refinamiento de operaciones y su representación. Se
portabilidad de un sistema,
pueden tener subclases y es fácil configurar una aplicación con una
indicando qué parte
instancia de esta clase extendida que se necesite en tiempo de
permite variar de forma
ejecución.
independiente
Permite un número variable de instancias. Facilita cambiar de
Evaluación de alternativas
opinión y permitir más de una instancia de la clase. Además, se puede
de diseño con la
utilizar el mismo enfoque para controlar el número de instancias que
comprensión de los costes y
utiliza la aplicación.
beneficios de aplicar el
patrón. Más flexible que operaciones de clase (static). Esta técnica hace que
sea difícil cambiar un diseño para permitir más de una instancia de
una clase. Y las subclases no pueden redefinirlas polimórficamente

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 11/117
19/1/2021 Patrones de Diseño

Clasificación
Patrón

Elemento de Patrón Nombre Patron Creacional Patrón Estructural Patrón de Comportamiento Propósito

+ composición estrucutras complejas + composición interaccones complejas


Extensibilidad Consecuencia Problema Solución + creación de objetos
+ (estructuras/datos) + (algoritmos/procesos)
+ ABeFes PiS
+ ABCDE!F y Punto + CC II MM O! SS en TV

Problema de Recurrente Motivación Aplicabilidad Intención

Problema de Diseño Problema de Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 12/117
19/1/2021 Patrones de Diseño

Patrones Creacionales
Patrón

Patron Creacional + creación de objetos


+ ABeFes PiS

Abstract Factory Buider Factory Method Prototype Singleton

Los clientes no tienen conocimiento (abstracción) sobre


las clases concretas que usan mediante sus clases abstractas
porque delegan a otras clases (creador) cómo se crean y se
Patron
asocian las instancias de las clases concretas que usa el Cliente Producto
Patrón Creacional
sistema.

ProductoConcretoA ProductoConcretoB

Menor Alta Bajo Menor Principio Abierto/Cerrado, con la


tamaño, cohesión, acoplamiento, complejidad, flexibilidad, extensibilidad, … para
abstrayéndose enfocándose conociendo con menor configuraciones de estruturas y
del proceso de en la gestión únicamente las tamaño, alta funcionalidades futuras. La configuración
creación de de los interfaces de cohesión y que puede ser estática (tiempo de
instancias productos. los objetos a bajo compilación) o dinámica (tiempo de
través de sus acoplamiento ejecución), añadiendo un objeto o una
clases anteriores. clase.
abstractas, sin
los
constructores
específicos

Abstract Factory
Problema

Motivación

Un cirujano opera Scenario


con el mismo
main()
algoritmo, pero
dependiendo de la
localización,
public operate() {
quirófano o selva o …, if (location == Location.OPERATING_ROOM) {
...
lo realizará con this.createCuttingToolScalpel();
cutting ToolScalpel.cut();
varios instrumentos «Director»
this.createDryingToolompress();
Surgeon
pertenecientes a «AbstractProductA»
dryingToolCompress.dry();
«AbstractProductB»
operate() ...
CuttingTool DryingTool
distintas familias create CuttingToolScalpel() } else if (location == Location.JUNGLE) {
create CuttingToolKnife() ...
equivalentes, cortante create DryingToolCompress() this.createCuttingToolKnife();
create DryingToolRag()
cuttingToolKnife.cut();
como bisturí o navaja o this.createDryingToolRag();
…, secante como dryingToolRag.dry();
}
compresa o trapo o … }

«ConcreteProductAA» «ConcreteProductAB» «ConcreteProductBA» «ConcreteProductBB»


Scalpel Knife Compress Rag

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que surgen


nuevas familias equivalentes.

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/AbstractFactory/abstractFactoryWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 13/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Surgeon (ej. 4) La cohesión de la La granularidad de la clase Surgeon (ej. 5)


depende del número de localizaciones y del clase Surgeon no es depende de la cantidad de métodos
número de familias de productos. adecuada puesto requeridos.
que asume varias
Se calcula como el producto del número Se calcula como la suma de los métodos
responsabilidades
de localizaciones (ej. selva y quirófano, 2) relativos a la responsabilidad de la
dispares o que no
por el número de familias de productos clase (ej. operate, 1) y el producto del
le atañen, como la
(ej. CuttingTool y DryingTool, 2), con la número de localizaciones por el
obtención del
simplificación de que no se comparten número de familias de productos (ej.
instrumental
instrumentos entre distintas selva y quirófano, 2, por CuttingTool y
dependiendo de la
localizaciones. DryingTool, 2).
localización
Su resultado es de orden cuadrático, (creación de Su resultado es de orden cuadrático,
O(n2). objetos). O(n2).

Intención

Si la responsabilidad
Scenario
de cirujano incluye
únicamente la main()

solicitud de
instrumental
abstracto (algo public operate(instrumentalist) {
...
cortante, algo secante,
«Director» instrumentalis.createCuttingTool();
…) y otros, Surgeon cutting Tool.cut();
instrumentalis.createDryingTool();
instrumentalistas, se operate(Instrumentalist) dryingTool.dry();
responsabilizan por ...
}
separado de cómo se
obtienen los
instrumentos
dependiendo de la «Abstract Factory»
Instrumentalist
localización, ninguna
createCuttingTool()
clase será compleja y createDryingTool()
se evitará la tendencia
a crecer.

«ConcreteFactoryA» «ConcreteFactoryB»
InstrumentalistinOperatingRoom «AbstractProductA» «AbstractProductB» InstrumentalistinJungle
CuttingTool DryingTool
createCuttingTool() createCuttingTool()
createDryingTool() createDryingTool()

«ConcreteProductAA» «ConcreteProductBA» «ConcreteProductAB» «ConcreteProductBB»


Scalpel Compress Knife Rag

Código de Ejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/AbstractFactory/abstractFactoryFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 14/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Surgeon (ej. 3) La cohesión de la La granularidad de la clase Surgeon (ej. 1)


depende del número de familias de clase Surgeon es depende de la cantidad de métodos
productos. adecuada puesto requeridos.
que asume una
Se calcula como la suma del Se calcula como la suma de los métodos
única
instrumentalista (ej. Instrumentalist, 1) relativos a la responsabilidad de la
responsabilidad,
más el número de familias de productos clase (ej. operate, 1).
centrada en la
(ej. CuttingTool y DryingTool, 2).
operación, Su resultado es de orden constante, O(1)
Su resultado es de orden lineal, O(n). colaborando con el
servicio del
instrumentalista y
los instrumentos
suministrados.

Intención Aplicabilidad

La intención de este patrón es Un sistema debe ser independiente de cómo se crean, componen y representan
proporcionar una interfaz para sus productos.
crear familias de objetos
Un sistema debe ser configurado con una familia de productos de entre varias.
relacionados o dependientes
Una familia de objetos producto relacionados está diseñada para ser usada
entre sí sin tener que especificar
conjuntamente, y es necesario hacer cumplir esta restricción.
su clase concreta
Se quiere proporcionar una biblioteca de clases de productos, y sólo se desea
revelar sus interfaces, no sus implementaciones.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 15/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Scenario
AbstractFactory: declara una
clase abstracta o interfaz que
main()
define los métodos de creación
de los distintos tipos de
AbstractProduct.
public doSomething() {
Director
... Tiene una operación que
abstractFactory.createProductA();
... devuelve un nuevo objeto
doSomething(abstractFactory) abstractFactory.createProductB();
} para cada clase abstracta de
producto. Los tipos de
producto está codificados en
las signaturas de las
Abstract Factory
operaciones. Añadir un nuevo
tipo de producto requiere
createProductA()
createProductB()

cambiar la interfaz de
AbstractFactory y todas las
clases que dependen de ella.
ConcreteFactoryA ConcreteFactoryB
AbstractProductA AbstractProductB
createProductA() createProductA()
Los clientes llaman a estas
createProductB() createProductB()
operaciones para obtener
instancias de productos, pero
no son conscientes de las
ConcreteProductAA ConcreteProductBA ConcreteProductAB ConcreteProductBB clases concretas que están
usando. En otras palabras, los
clientes no tienen que atarse
a una clase concreta, sino sólo
a una interfaz definida por
una clase abstracta.

AbstractProduct: declara una clase abstracta o interfaz para un tipo de objeto producto.

ConcreteFactory: clase derivada de AbstractFactory que implementa los métodos para crear objetos producto concretos.

El modo más común de hacer esto es definiendo un método de fabricación para cada producto.

ConcreteProduct: clase derivada del AbstractProduct que representa un producto concreto para un estándar concreto de
interfaz de usuario.

Implementación

Variaciones
Un diseño más flexible, aunque menos seguro, es añadir un parámetro a las operaciones que crean los objetos. Este
parámetro especifica el tipo de objeto a ser creado. Podría tratarse de un identificador de clase, un entero, una cadena de texto
o cualquier otra cosa que identifique el tipo de producto. De hecho, con este enfoque, AbstractFactory solo necesita una única
operación create con un parámetro que indique el tipo de objeto a crear.

Podemos aplicarla en Java, C++, etc. sólo cuando todos los objetos tienen la misma clase abstracta o cuando los objetos
producto pueden ser convertidos con seguridad al tipo concreto por el objeto que lo solicita. Pero incluso cuando no es
necesaria la conversión de tipos, todavía subyace un problema inherente: todos los productos se devuelven al cliente con la
misma interfaz abstracta que el tipo de retorno. El cliente no podrá por tanto distinguir o hacer suposiciones seguras acerca
de la clase de un producto. En caso de que los clientes necesiten realizar operaciones específicas de las subclases,
éstas no estarán accesibles a través de la interfaz abstracta. Aunque el cliente podría hacer una conversión al tipo de
una clase hija, eso no siempre resulta viable o seguro, porque la conversión de tipo puede fallar. Éste es el inconveniente
típico de una interfaz altamente flexible y extensible.

Consecuencias

Ventajas Desventajas

El patrón Abstract Factory ayuda a controlar las clases de objetos que crea una Ampliar la AbstractFactory para
aplicación. Como una AbstractFactory encapsula la responsabilidad y el proceso de producir nuevos tipos de
creación de objetos producto, aísla a los clientes de las clases de implementación. productos no es fácil. Esto se
Los clientes manipulan las instancias a través de sus interfaces abstractas. Los debe a que la interfaz
nombres de las clases producto quedan aisladas en la implementación de la AbstractFactory fija el conjunto
ConcreteFactory; no aparecen en el código cliente. de productos que se pueden
crear.
La clase ConcreteFactory sólo aparece una vez en una aplicación, cuando se crea.
Esto facilita cambiar la ConcreteFactory que usa una aplicación. Como una Permitir nuevos tipos de
AbstractFactory crea una familia completa de productos, toda la familia de productos requiere ampliar la
productos cambia de una vez. interfaz, lo que a su vez
implica cambiar la clase
Cuando se diseñan objetos producto en una familia para trabajar juntos, es
AbstractFactory y todas sus
importante que una aplicación use objetos de una sola familia a la vez. El patrón
subclases.
Abstract Factory facilita que se cumpla esta restricción.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 16/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Granularidad Crear un objeto especificando su clase Acoplamiento
explícitamente

Especificar la implementación de los Implementación Dependencias de plataformas hardware o Acoplamiento


objetos software

Dependencias de las representaciones o Acoplamiento


implementaciones de objetos

Fuerte acoplamiento Acoplamiento

Builder
Problema

Motivación

Una persona se
Scenario
responsabiliza de
una dieta variada main()
de menús, básico o
gourmet o …, todos
ellos compuestos
por diferentes public eat() {
platos: entrante, if(dish == Dish.BASIC) {
...
ensalada u ostras o this.prepareSalad();
Person
…; plato principal, this.prepareChicken();
pollo o solomillo o this.prepareCustard();
eat()
...
…; postre, natillas o prepareSalad()
} else if (dish == Dish.Gourmet) {
prepareChiken()
soufflé o … prepareCustard() ...
prepareOyster() this.prepareOyster();
prepareSirloin() this.prepareSirloin();
prepareSouffle() this.prepareSouffle();
...
}
}

Salad Chicken Custard Oyster Sirloin Souffle

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevos platos.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Builder/builderWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 17/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 6) La cohesión de la La granularidad de la clase Person (ej. 7)


depende del número de tipos de menú y del clase Person no es depende de la cantidad de métodos
número de platos del menú. adecuada puesto requeridos.
que asume varias
Se calcula como el producto del número de Se calcula como la suma de los métodos
responsabilidades
tipos de menú (ej. básico y gourmet, 2) por el relativos a la responsabilidad de la clase
dispares o que no
número de platos del menú (ej. entrante, (ej. eat, 1) y el producto del número de
le atañen, como la
plato principal y postre, 3), con la tipos de menús por el número de platos
preparación de
simplificación de que no se comparten platos del menú (ej. básico y gourmet, 2, por
diferentes platos
en diferentes menús. entrante, plato principal y postre, 3).
dependiendo del
Su resultado es de orden cuadrático, O(n2). tipo de menú de su Su resultado es de orden cuadrático, O(n2).
dieta (creación de
objetos).

Intención

Si la Scenario

responsabilidad main()

de la persona
incluye
public eat(Chef) {
únicamente la «Director»
...
chef.prepareStarter();
solicitud del Person
chef.prepareMainCourse();
chef.prepareDessert();
eat(Chef)
menú (básico, }
...

gourmet, …) y otros,
cocineros, se
responsabilizan «AbstractBuilder»
Chef

por separado de prepareStarter()


prepareMainCourse()
cómo se preparan prepareDessert()

los platos del


menú «ConcreteBuilderA» «ConcreteBuilderB»

dependiendo del BasicChef GourmetChef

prepareStarter() prepareStarter()
tipo de menú, prepareMainCourse() prepareMainCourse()
prepareDessert() prepareDessert()
ninguna clase será
compleja y se
evitará la tendencia «AbstractProduct»
Dish

a crecer.

«ConcreteProductA» «ConcreteProductB» «ConcreteProductC» «ConcreteProductD» «ConcreteProduct>E» «ConcreteProductF»


Salad Chicken Custard Oyster Sirloin Souffle

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Builder/builderFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 18/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 2) La cohesión de la La granularidad de la clase Person (ej. 1)


depende del tipo del cocinero (ej. Chef, 1) y clase Person es depende de la cantidad de métodos
del tipo del plato del menú (ej. Dish, 1). adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. eat, 1).
centrada en comer,
colaborando con el
servicio del
Su resultado es de orden constante, O(1).
cocinero que
suministra los
platos.

Intención Aplicabilidad

La intención de este patrón es El algoritmo para la creación de un objeto complejo debe ser independiente de
separar la construcción de un las partes que componen el objeto y la forma en que están montadas.
objeto complejo de su
El proceso de construcción debe permitir diferentes representaciones para el
representación, de tal forma
objeto que se construye.
que el mismo proceso de
construcción puede crear
diferentes representaciones.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 19/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Director: clase que solicita la


Scenario
creación de un objeto utilizando
la interfaz proporcionada por el
main()
AbstractBuilder.

AbstractBuilder: declara una


clase abstracta o interfaz que
public build { define una operación para cada
Director componente que un Director
for each element in product {
builder.buildPart(); puede pedirle crear.
build()
}
Las operaciones no hacen
nada por defecto.

Los constructores construyen


sus productos paso a paso.
AbstractBuilder
Por tanto, la interfaz de la
buildPart() clase AbstractBuilder debe ser
prepareMainCourse() lo suficientemente general
prepareDessert()
como para permitir construir
productos por parte de todos
los tipos de ConcreteBuilder.

ConcreteBuilderA ConcreteBuilderB
AbstractProduct
buildPart() buildPart()
getResult() getResult()

ConcreteProductA ConcreteProductB

ConcreteBuilder: clase derivada de AbstractBuilder que redefine las operaciones de construcción de las piezas en las que
está interesado para la creación del producto final. Se encarga también de ensamblar dichas piezas para componer el
ConcreteProduct y devolver una instancia de este.

A veces, podríamos necesitar acceder a las partes del producto que ya fueron construidas. Con las estructuras arbóreas
que se crean de abajo a arriba, el ConcreteBuilder devolvería nodos hijos al Director, el cual los devolvería al constructor
para construir los nodos padre.

AbstractProduct: declara una clase abstracta o interfaz para un tipo de objeto producto.

ConcreteProduct: clase derivada del AbstractProduct que representa un producto concreto.

En general, los ConcreteProduct creados por los ConcreteBuilder tienen representaciones tan diferentes que suele ser de
poca utilidad definir una clase padre común AbstractProduct para los diferentes productos.

Normalmente, como el cliente suele configurar al Director con el ConcreteBuilder adecuado, sabe qué subclase concreta
de Builder se está usando y puede manejar sus productos en consecuencia.

Implementación

Variaciones
En general, los ConcreteProduct creados por los ConcreteBuilder tienen representaciones tan diferentes que suele ser de poca
utilidad definir una clase padre común AbstractProduct para los diferentes productos.

Consecuencias

Ventajas Desventajas

Se proporciona al Director una interfaz abstracta para la construcción del producto.


La interfaz permite al ConcreteBuilder ocultar la representación y la
estructura interna del producto. También oculta cómo el producto se ensambla.
Debido a que el producto se construye a través de una interfaz abstracta, todo lo que
tiene que hacer para cambiar la representación interna del producto es definir un
nuevo tipo de ConcreteBuilder.

Mejora la modularidad encapsulando la forma en que un objeto complejo es


construido y representado. Cada ConcreteBuilder contiene toda la funcionalidad
necesaria para crear y ensamblar un tipo concreto de producto. Los clientes no
necesitan saber nada acerca de las clases que definen la estructura interna del
producto; estas clases no aparecen en la interfaz del Builder.

Construye el producto paso a paso bajo el control del Director. Sólo cuando el


producto está terminado, el Director lo recupera desde el ConcreteBuilder. Por lo
tanto, la interfaz del ConcreteBuilder refleja el proceso de construcción del producto,
pudiendo coordinar y validar la creación de todos los componentes. Esto le da un
mayor control sobre el proceso de construcción y, por lo tanto, de la estructura
interna del producto resultante.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 20/117
19/1/2021 Patrones de Diseño

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Granularidad Dependencias algorítmicas Acoplamiento

Especificar la implementación de los Implementación


objetos

Factory Method
Problema

Motivación

Un repartidor se
Scenario
responsabiliza
del reparto de
main()
paquetes con el
mismo algoritmo,
recoger paquete,
localización del
public deliver() {
destino, seleccionar
...
vehículo disponible, if (vehicle == AvailableVehicle.BYCYCLE) {
conducir, entregar this.getBicycle();
paquete, … pero } else if (vehicle == AvailableVehicle.MOTORCYCLE) {
dependiendo de this.getMotocycle();
DeliveryMan }
los tipos de
...
vehículo }
deliver()
disponibles, lo getBicycle()
realizará con un getMotocycle() public getBicycle {
return new Bicycle();
vehículo u otro,
}
bicicleta o moto o …
public getMotorcycle() {
return new Motorcycle();
}

«AbstractProduct»
Vehicle

«ConcreteProductA» «ConcreteProductB»
Bicycle Motorcycle

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevos vehículos.

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/FactoryMethod/factoryMethodWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 21/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase DeliveryMan (ej. La cohesión de la La granularidad de la clase DeliveryMan (ej.


3) depende del número de vehículos. clase DeliveryMan 3) depende de la cantidad de métodos
no es adecuada requeridos.
Se calcula como la suma del tipo de
puesto que asume
vehículo (ej. Vehicle, 1) más el número de Se calcula como la suma de los métodos
varias
vehículos (ej. Bicycle y Motorcycle, 2). relativos a la responsabilidad de la clase
responsabilidades
(ej. deliver, 1) y el número de vehículos (ej.
Su resultado es de orden lineal, O(n). dispares o que no
Bicycle y Motorcycle, 2).
le atañen, como la
obtención del Su resultado es de orden lineal, O(n).
vehículo
dependiendo de los
tipos de vehículos
disponibles
(creación de
objetos).

Intención

Si la Scenario

responsabilidad
main()
de repartidor
incluye
únicamente la public deliver() { «Creator»
...
solicitud de un this.getVehicle();
DeliveryMan

vehículo }
... getVehicle()
deliver()

abstracto y otros,
repartidores
concretos, se «ConcreteCreatorA» «ConcreteCreatorB»
public getVehicle() «AbstractProduct» public getVehicle() {
CyclistDeliveryMan MotorcyclistDeliveryMan
responsabilizan return new Bicycle(); Vehicle return new Motorcycle();
} }
por separado de
getVehicle() getVehicle()

cómo se obtiene el
vehículo concreto
«ConcreteProductA» «ConcreteProductB»
dependiendo de Bicycle Motorcycle

los vehículos
disponibles,
ninguna clase será
compleja y se
evitará la tendencia
a crecer.

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/FactoryMethod/factoryMethodFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 22/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase DeliveryMan (ej. La cohesión de la La granularidad de la clase DeliveryMan (ej.


1) depende del tipo del vehículo (ej. Vehicle, clase DeliveryMan 2) depende de la cantidad de métodos
1). es adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. deliver, 1) y el método para obtener el
centrada en el
vehículo (ej. getVehicle).
reparto,
colaborando con el Su resultado es de orden constante, O(1).
servicio del
repartidor concreto
y el vehículo
suministrado.

Intención Aplicabilidad

La intención de este patrón es Una clase no puede prever la clase de objetos que debe crear.
definir una interfaz para
Una clase quiere que sean sus subclases quienes especifiquen los objetos que
crear un objeto, pero delegar
ésta crea.
a las subclases qué clase
concreta instanciar, Las clases delegan la responsabilidad en una de entre varias clases auxiliares y
permitiendo a una clase queremos localizar qué subclase de auxiliar concreta es en la que se delega.
diferir la instanciación a las
subclases.

Solución

Estructura General Participantes

Scenario Creator: declara una clase


main() abstracta o interfaz que define
los métodos de fabricación

public doSomething() {
(Factory Method) de los distintos
Creator
...
this.factoryMethod();
tipos de ConcreteProduct.
... factoryMethod()
doSomething()
}
Podría tratarse también de
una clase concreta que
public getConcreteProductA() { ConcreteCreatorA ConcreteCreatorB public getConcreteProductB() { proporcione una
AbstractProduct
return new ConcreteProductA(); return new ConcreteProductB();
} factoryMethod() factoryMethod() } implementación
predeterminada del método
de fabricación. 
ConcreteProductA ConcreteProductB

AbstractProduct: declara una clase abstracta o interfaz para un tipo de objeto producto.

ConcreteCreator: clase derivada de Creator que implementa el método de fabricación (Factory Method) para crear su
correspondiente ConcreteProduct.

ConcreteProduct: clase derivada del AbstractProduct que representa un producto concreto para un estándar concreto de
interfaz de usuario.

Implementación

Variaciones
Las dos principales variantes del patrón Factory Method son:

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 23/117
19/1/2021 Patrones de Diseño

La clase Creator es una clase abstracta y no proporciona una implementación para el método de fabricación que
declara. Requiere que las subclases definan una implementación porque no hay ningún comportamiento predeterminado
razonable.

La clase Creator es una clase abstracta (menos común) o concreta y proporciona una implementación predeterminada
del método de fabricación. El ConcreteCreator usa el método de fabricación principalmente por flexibilidad. Lo hace
siguiendo una regla que dice: “crear objetos en una operación aparte, para que las subclases puedan redefinir el modo en
que son creados”. Esta regla asegura que los diseñadores de las subclases puedan cambiar la clase de objetos.

Otra variante del patrón permite que los métodos de fabricación creen varios tipos de productos. El método de
fabricación recibe un parámetro que identifica el tipo de objeto a crear. Todos los objetos creados por el método compartirán
la interfaz AbstractProduct.

Un potencial problema de los métodos de fabricación es que pueden obligar a usar la herencia sólo para crear los objetos
ConcreteProduct apropiados. Otra forma de hacer esto es proporcionar una subclase genérica de Creator
parametrizada con la clase de ConcreteProduct.

Consecuencias

Ventajas Desventajas

Los clientes pueden encontrar útiles los métodos de Un inconveniente potencial de los métodos de fabricación
fabricación, especialmente en el caso de jerarquías de es que los clientes pueden tener que crea subclases de
clases paralelas. Creator sólo para fabricar un nuevo tipo de
ConcreteProduct. La herencia está bien siempre y
Las jerarquías de clases paralelas se producen cuando
cuando el cliente tenga que crear las subclases de
una clase delega alguna de sus responsabilidades a una
todos modos, ya que, si no, se estaría introduciendo
clase separada (como las clases de estructuras de datos
una nueva vía de futuros cambios.
y la obtención de sus iteradores). Los métodos de
fabricación definen la conexión entre las dos jerarquías
de clases, localizando qué clases van juntas.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar la implementación de los Implementación Crear un objeto especificando su clase Acoplamiento


objetos explícitamente

Prototype
Problema

Motivación

En un parque, un
Scenario
poeta se
responsabiliza de
main()
vender poemas
famosos que
escribe en el
momento en que se
public sell(poemid) {
lo piden porque se
if (poemid == "La Casada Infiel") { Poet
los sabe de return this.createLaCasadaInfiel();
memoria. Pero si } else if (poemid == "PoemaXX") { sell(poemid)
cambian los gustos, return this.createPoemaXX(); createLaCasadaInfiel()
tendrá que } createPoemaXX()
}
adaptarse y
aprender nuevos
poemas.

Poem

LaCasadaInfiel PoemaXX

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevos poemas.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Prototype/prototypeWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 24/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Poet (ej. 3) La cohesión de la La granularidad de la clase Poet (ej. 3)


depende del número de poemas. clase Poet no es depende de la cantidad de métodos
adecuada puesto requeridos.
Se calcula como la suma del tipo de poema
que asume varias
(ej. Poem, 1) más el número de poemas (ej. Se calcula como la suma de los métodos
responsabilidades
LaCasadaInfiel y PoemaXX, 2). relativos a la responsabilidad de la clase
dispares o que no
(ej. sell, 1) y el número de poemas (ej.
Su resultado es de orden lineal, O(n). le atañen, como la
LaCasadaInfiel y PoemaXX, 2).
venta y la creación
del poema concreto Su resultado es de orden lineal, O(n).
que ha sido
solicitado (creación
de objetos).

Intención

Si la
Scenario
responsabilidad
de poeta incluye
main()
únicamente la
solicitud de una
copia del poema
solicitado y otros,
public sell(poem, poemid) {
poemas
... «Director»
concretos, se requestedPoem = poem.getPoem(poemid) Poet
responsabilizan requestedPoem.copy();
por separado de ... sell(poemid)

cómo se obtiene la }
copia del poema,
ninguna clase será
compleja y se
evitará la tendencia «Prototype»
a crecer. Poem

getPoem()
copy()

«ConcretePrototypeA» «ConcretePrototypeB»
LaCasadaInfiel PoemaXX

copy() copy()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Prototype/prototypeFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 25/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Poet (ej. 1) La cohesión de la La granularidad de la clase Poet (ej. 1)


depende del tipo del poema (ej. Poem, 1). clase Poet es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume una
Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. sell, 1.
centrada en la
venta sin saber Su resultado es de orden constante, O(1).
nada de poesía; se
ha convertido en
algo que parece un
poeta, pero es un
mero
suministrador de
poesías.

Intención Aplicabilidad

La intención de este patrón es Un sistema deba ser independiente de cómo se crean, se componen y se
especificar las clases de representan sus productos y se cumpla alguna de las siguientes condiciones:
objetos a crear usando una
Las clases a instanciar sean especificadas en tiempo de ejecución (por ejemplo,
instancia prototípica y crear
mediante carga dinámica).
nuevos objetos por copias de
este prototipo. Se quiera evitar construir una jerarquía de clases fábrica paralela a la
jerarquía de clases de los productos.

Las instancias de una clase puedan tener uno de entre sólo unos pocos estados
diferentes. En esta situación puede ser más adecuado tener un número
equivalente de prototipos y clonarlos, en vez de crear manualmente instancias de
la clase cada vez con el estado apropiado.

Solución

Estructura General Participantes

Scenario
Prototype: declara una clase
abstracta o interfaz para
main()
clonarse.

public doSomething(Prototype, prototipeid) {


...
Director
requestedPrototype = prototype.getPrototype(prototipeid)
requestedPrototype.clone();
... doSomething(Prototype, prototipeid)
}

Prototype

clone()

ConcretePrototypeA ConcretePrototypeB

clone() clone()

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 26/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

ConcretePrototype: clase derivada de Prototype que implementa el método de clonación. El método de clonación devuelve
una instancia de la misma clase con los mismos valores que la instancia Prototype original. La nueva instancia puede ser
una copia profunda o superficial del original.

Director: clase que solicita la creación de un objeto utilizando la interfaz de clonación proporcionada por Prototype.

Implementación

Variaciones

Cuando el número de prototipos de


Scenario
un sistema no es fijo, y éstos
pueden crearse y destruirse
main()
dinámicamente, se puede utilizar
un registro de los prototipos
disponibles. Los clientes no
gestionarían ellos mismos los
public sell(poetry, poemid) {
prototipos, sino que los guardarán
... «Director»
y recuperarán del registro. Un requestedPoem = poetry.getPoem(poemid) Poet
cliente le pedirá al registro un requestedPoem.copy();
prototipo antes de clonarlo. ... sell(poemid)
}
Este gestor de prototipos es un
almacén asociativo que
devuelve el prototipo que
concuerda con una determinada
«PrototypeRegistry»
clave. Tiene operaciones para
Poetry
registrar un prototipo con una
clave y para desregistrarlo. Los addPoem(Poem)()
remuvePoem(Poem)
clientes pueden cambiar el getPoem(poemid)
registro o incluso navegar por él
en tiempo de ejecución. Esto
permite que los clientes
extiendan el sistema y lleven
Poem
un inventario del mismo sin
necesidad de escribir código.
copy()

«ConcretePrototypeB» «ConcretePrototypeA»
PoemaXX LaCasadaInfiel

copy() copy()

Código ejemplo
(https://github.com/USantaTecla-
disenyo/designPatterns/tree/master/src/main/java/usantatecla/Prototype/prototypeFineWithRegistry)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 27/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Poet (ej. 1) La cohesión de la La granularidad de la clase Poet (ej. 1)


depende del tipo del registro de poemas (ej. clase Poet es depende de la cantidad de métodos
Poetry, 1). adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. sell, 1.
centrada en la
venta, colaborando Su resultado es de orden constante, O(1).
con el servicio de
registro de poemas
y la copia
suministrada.

En cuanto al método de clonación, que es la parte más complicada de implementar del patrón Prototype (especialmente
cuando las estructuras de objetos contienen referencias circulares), existen dos variantes, copia superficial y copia profunda:

Copia superficial: sólo duplica los elementos de alto nivel de una clase; esto proporciona una copia más rápida, pero no
siempre resulta apropiada (los objetos de bajo nivel son compartidos entre las copias del objeto, por lo que cualquier
cambio en ellos afectaría a todas las copias).

Copia profunda: duplica tanto los atributos de alto nivel como los objetos de bajo nivel. Esto suele llevar más tiempo y
puede ser costoso para objetos con una estructura compleja, pero asegura que los cambios en una copia se aíslan de las
otras copias. Mediante la copia profunda se garantiza que el clon y el original son independientes, es decir, que los
componentes del clon son clones de los componentes del prototipo.

La mayoría de los lenguajes proporcionan algún tipo de ayuda para clonar objetos (clone(), constructor de copia, …). Pero
estas facilidades no resuelven el problema de la copia superficial frente a la copia profunda. La clonación nos obliga a
decidir qué será compartido, si es que lo será algo.

Mientras que a algunos clientes les sirve el clon tal cual, otros necesitarán inicializar parte de su estado interno, o todo, con
valores de su elección. Generalmente no se pasan dichos valores en la operación clonar ya que esto impediría tener una
interfaz de clonación uniforme, puesto que el número de valores a inicializar variará de unas clases de prototipos a otras
(algunos prototipos pueden necesitar múltiples parámetros de inicialización; otros no necesitarán ninguno).

Puede darse el caso de que nuestras clases prototipo ya definan operaciones para establecer las partes principales de su
estado. Si es así, los clientes pueden usar estas operaciones inmediatamente después de la clonación.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 28/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

Oculta al cliente las clases producto concretas, reduciendo así el número de nombres que conocen los
clientes. Además, permite que un cliente use las clases específicas de la aplicación sin cambios.

Permite incorporar a un sistema una nueva clase concreta de producto simplemente registrando
una instancia prototípica con el cliente. Esto es algo más flexible que otros patrones de creación, ya que
un cliente puede instalar y eliminar prototipos en tiempo de ejecución.

Los sistemas altamente dinámicos permiten definir comportamiento nuevo mediante la


composición de objetos – por ejemplo, especificando valores para las variables de un objeto – y no
definiendo nuevas clases. Podemos definir nuevos tipos de objetos creando instancias de clases existentes
y registrando esas instancias como prototipos de los objetos cliente. Un cliente puede exhibir
comportamiento nuevo delegando responsabilidad en su prototipo.

Este tipo de diseño permite que los usuarios definan nuevas “clases” sin programación. De hecho, clonar
un prototipo es parecido a crear una instancia de una clase. El patrón prototipo puede reducir en gran
medida el número de clases necesarias en un sistema.

El patrón Prototype permite reducir la herencia. Los patrones Abstract Factory y Factory Method suele
producir una jerarquía de clases AbstractFactory y Creator que es paralela a la jerarquía de clases de
productos. El patrón Prototype permite clonar un prototipo en vez de decirle a un método de fabricación
que cree un nuevo objeto. Por tanto, no es en absoluto necesaria una jerarquía de clases AbstractFactory o
Creator. Este beneficio es aplicable principalmente a lenguajes como Java, C++, etc. que no tratan a las
clases como objetos en toda regla.

Algunos entornos de tiempo de ejecución permiten cargar clases en una aplicación dinámicamente. El


patrón Prototype es la clase para explotar dichas facilidades en un lenguaje como Java, C++, etc. Una
aplicación que quiere crear instancias de una clase cargada dinámicamente no podrá hacer referencia al
constructor de ésta estáticamente.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar la implementación de los Implementación Crear un objeto especificando su clase Acoplamiento


objetos explícitamente

Singleton
Problema

Motivación

Una escuela es una institución


Scenario
que consta de distintas
entidades, dirección o main()

departamentos o …, las cuales


están constituidas por
profesores. Además, se School
dispone de un guardia de
School()
seguridad cuyos servicios son startAcademicYear()

requeridos por éstos. La


ausencia de un mecanismo
global para localizarle obliga
ManagementBoard Departament
a que se tenga que presentar
al guardia a todas las clases ManagementBoard(SecurityGuard) Departament(String, SecurityGuard)

organizativas para que éste


llegue a ser conocido por los
profesores y, en caso de public Professor (String, SecurityGuard) {
necesitar ser sustituido, de this.title = title;
this.securityGuard = securityGuard;
avisarles de dicha sustitución }
Professor
para que puedan seguir
public teach() {
utilizando sus servicios. this.securityGuard.openClassRoom(); Professor(String, SecurityGuard)
teach()
// Teaching
...
this.securityGuard.closeClassRoom();
}

SecurityGuard

openSchool()
openClassRoom()
closeClassRoom()
provideSchoolKeys()

Esto tiende a crecer a medida que surgen nuevas clases organizativas a las que
será necesario presentar al guardia de seguridad aunque no requieran sus
servicios.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 29/117
19/1/2021 Patrones de Diseño

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Singleton/singletonWrong)

Acoplamiento Cohesión Granularidad

El acoplamiento de las clases organizativas La cohesión de las La granularidad de las clases organizativas
(School, ManagementBoard y Department) clases (School, ManagementBoard y Department)
varía para cada tipo de clase organizativa. En organizativas depende de la cantidad de parámetros
el caso de la clase School, depende del (School, requeridos en su constructor y del
número de entidades y del guardia de ManagementBoard parámetro correspondiente al guardia de
seguridad; y en el caso de las entidades y Department) no es seguridad. Dicha cantidad varía para cada
ManagementBoard y Department, depende adecuada puesto tipo de participante (ej. School, 0 + 1 = 1;
del tipo del profesor y del guardia de que asume varias ManagementBoard, 0 + 1 = 1; Department, 0 +
seguridad. responsabilidades 1 = 1), por lo que se considerará para el
dispares o que no análisis la media de todos los parámetros
Al tratarse de una cantidad que varía para
le atañen, como el de los constructores de las clases que
cada tipo de clase organizativa (ej. School, 3;
conocimiento del representan a los distintos tipos de clase
ManagementBoard, 2; Department, 2), se
guardia de organizativa (ej. 1).
considerará para el análisis la media de los
seguridad para que
acoplamientos de las clases que Se calcula como la media de los parámetros
éste pueda ser
representan a los distintos tipos de clases de los constructores de las clases que
presentado a los
organizativas (ej. 2,3). representan a los distintos tipos de clase
profesores.
organizativa más el parámetro del
Su resultado es de orden lineal, O(n).
guardia de seguridad; es decir, la suma de
los parámetros de los constructores de todas
las clases que representan un tipo de clase
organizativa (ej. 1 + 1 + 1 = 3) dividido entre el
número de tipos de clases organizativas (ej.
3).

Su resultado es de orden lineal, O(n).

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 30/117
19/1/2021 Patrones de Diseño

El uso de un
Scenario
servicio de guardia
de seguridad
main()
global permite la
flexibilidad de
localizar e
incluso cambiar
«Director»
de guardia sin
School
afectar a nadie.
School()
startAcademicYear()

ManagementBoard Departament

ManagementBoard() Departament()

public Professor (String) {


this.title = title;
this.securityGuard = securityGuard.getInstance();
}
Professor
public teach() {
this.securityGuard.openClassRoom(); Professor()
teach()
// Teaching
...
this.securityGuard.closeClassRoom();
}

«Singleton»
public getInstance() { SecurityGuard
if (securityGuard == null) { Printer printer
securityGuard = new SecurityGuard();
getInstance()
}
openSchool()
return securityGuard; openClassRoom()
} closeClassRoom()
provideSchoolKeys()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Singleton/singletonFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 31/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de las clases organizativas La cohesión de la La granularidad de las clases organizativas


(School, ManagementBoard y Department) clase School es (School, ManagementBoard y Department)
varía para cada tipo de clase organizativa. En adecuada puesto depende de la cantidad de parámetros
el caso de la clase School, depende del que asume una requeridos en su constructor. Dicha
número de entidades; y en el caso de las única cantidad varía para cada tipo de participante
entidades ManagementBoard y Department, responsabilidad, (ej. School, 0; ManagementBoard, 0;
depende del tipo del profesor. centrada en el Department, 0), por lo que se considerará
arranque del curso para el análisis la media de todos los
Al tratarse de una cantidad que varía para
académico, parámetros de los constructores de las
cada tipo de clase organizativa (ej. School, 2;
ignorando la clases que representan a los distintos
ManagementBoard, 1; Department, 1), se
existencia del tipos de clase organizativa (ej. 0).
considerará para el análisis la media de los
guardia de
acoplamientos de las clases que Se calcula como la media de los parámetros
seguridad.
representan a los distintos tipos de clases de los constructores de las clases que
organizativas (ej. 1,3). representan a los distintos tipos de clase
organizativa; es decir, la suma de los
Su resultado es de orden lineal, O(n).
parámetros de los constructores de todas las
clases que representan un tipo de clase
organizativa (ej. 0 + 0 + 0 = 0) dividido entre el
número de tipos de clases organizativas (ej.
3).

Su resultado es de orden lineal, O(n).

Intención Aplicabilidad

La intención de este patrón es Se requiere exactamente una única instancia de una clase y debe ser accesible a los
asegurar que una clase tenga clientes desde un punto de acceso bien conocido.
una sola instancia y proveer
Se precisa que la única instancia sea extensible por subclasificación de tal manera
un punto de acceso global
que los clientes puedan ser capaces de usar la instancia extendida sin modificar su
para ésta.
código,

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 32/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Singleton: responsable de crear


Scenario
y almacenar su propia instancia
única. Define una operación de
main()
clase getInstance que permite a
los clientes acceder a su única
instancia.

Director

public getInstance() { Singleton


if (uniqueInstance == null) {
uniqueInstance
uniqueInstance = new Singleton(); singletonData
}
return uniqueInstance; getInstance()
getSingletonData()
} performSingletonOperations()

Implementación

Variaciones

Se puede subclasificar el Singleton para devolver una instancia polimórfica Scenario

utilizando diversos mecanismos: main()

La utilización de variables de entorno y sentencias condicionales para


determinar la subclase es más flexible, pero implica fuertes conexiones al «Director»
School
conjunto de posibles clases Singleton.
School()
startAcademicYear()

Situar la implementación de getInstance fuera de la clase padre (por ejemplo,


en una Factoría) o ponerla en la subclase. Esto permite decidir la clase de Singleton
en tiempo de compilación. ManagementBoard Departament

ManagementBoard() Departament()
La utilización de un registro de objetos Singleton. En lugar de definir el conjunto
de posibles clases Singleton en getInstance, las clases Singleton pueden registrar su
única instancia por su nombre en un registro conocido (por ejemplo, en su public Professor(
this.title = title;
constructor). Código de ejemplo }
this.securityGua

Professor
(https://github.com/miw-
public teach() {
upm/IWVG/tree/master/doo/src/main/java/designPatterns/patterns/singleton/v6/subclassifing/cpp) Professor(String}
teach()
this.securityGua
// teaching
...
this.securityGua
}

public getInstance() { «Singleton»


if (securityGuard == null) { SecurityGuard
name = getSingletonConfigure(); Printer printer
securityGuard = (SecurityGuard) (Class.forName
("." + name).newInstance()); getInstance()
openSchool()
} openClassRoom()
return securityGuard; closeClassRoom()
} provideSchoolKeys()

PublicSecurityGuard PrivateSecurityGuard

openSchool() openSchool()
openClassRoom() openClassRoom()
closeClassRoom() closeClassRoom()
provideSchoolKeys() provideSchoolKeys()

Cógigo de ejemplo
(https://github.com/USantaTecla-
disenyo/designPatterns/tree/master/src/main/java/usantatecla/Singlet

Consecuencias

Ventajas Desventajas

Permite tener un control estricto sobre cómo y cuándo los clientes acceden a la
instancia única de la clase.

Supone una mejora sobre el uso de variables globales ya que evita contaminar el
espacio de nombres con variables globales que almacenen las instancias.

Permite tener subclases y es fácil configurar una aplicación con una instancia de
una clase extendida que se necesite en tiempo de ejecución.

Facilita cambiar de opinión y permitir más de una instancia de la clase. Además, se


puede utilizar el mismo enfoque para controlar el número de instancias que
utiliza la aplicación, modificando únicamente la operación que otorga acceso a la
instancia del Singleton.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 33/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Especificar la implementación de los Implementación


objetos

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 34/117
19/1/2021 Patrones de Diseño

Patrones Estructurales
Patrón

+ composición estrucutras complejas


Patrón Estructural
+ (estructuras/datos)
+ ABCDE!F y Punto

Adapter Bridge Composite Decorator Facade Flyweight Proxy

se ocupan de cómo se combinan las se basan en un mismo pequeño tienen estruturas de clases muy
clases y los objetos para formar conjunto de mecaninsmos del similares que ocultan los
estructuras más grandes. lenguaje para estructurar el código: diferentes propósitos de estos
herencia de clases simple y patrones.
múltiple y composición de objetos

Adapter
Problema

Motivación

Cuando se viaja al extranjero, existen problemas al enchufar los aparatos eléctricos (secador de pelo, maquinilla de afeitar,
…) porque el número, forma y/o disposición de las patillas de los enchufes no son iguales en todos los países, ya que existen
distintos estándares.

Un solución costosa y engorrosa sería comprar nada más llegar al destino todos los aparatos eléctricos con el
estándar del país de destino y guardarlos en el trastero hasta que se vuelva a viajar a un país del mismo estándar.

Scenario Esto complica la


ApplianceC ApplianceF

main()
comprensión de
su comportamiento
y tiende a crecer a
ShaverC HairdryerC
PowerplugC PowerPlugF
ShaverF HairdryerF medida que
plug(PowerPointC) plug(PowerPoitF) surgen nuevos
países de destino

PowerPointC PowerPointF

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Adapter/adapterWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 35/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Scenario (ej. 6) La cohesión de la La granularidad de la clase Scenario (ej. 6)


depende del número de aparatos eléctricos clase Scenario no es depende del número de aparatos eléctricos
y del número de distintos estándares. adecuada puesto y del número de distintos estándares.
que asume varias
Se calcula como el producto del número de Se calcula como el producto del número de
responsabilidades
estándares (ej. C y F, 2) por el número de estándares (ej. C y F, 2) por el número de
dispares o que no
aparatos eléctricos (ej. secador y maquinilla aparatos eléctricos (ej. secador y maquinilla
le atañen, como la
de afeitar, 2) más el enchufe (ej. de afeitar, 2) más el enchufe (ej.
gestión de aparatos
PowerPointC o PowerPointF, 1). PowerPointC o PowerPointF, 1).
dependiendo del
Su resultado es de orden cuadrático, O(n2). estándar de destino Su resultado es de orden cuadrático, O(n2).
(creación de
objetos).

Intención

Otra solución «Target»


Scenario public void plug (PowerPointC) {
barata y sencilla es ApplianceC PowerPlugF
this.powerPlugC.plug(PowerPointC);
mantener los main() }
plug(PowerPointF)

aparatos
eléctricos del
origen y «Adapter»
únicamente HairdryerC ShaverC PowerPointF AdapterPawerPlugF

comprar plug(PawerPointC)

adaptadores
antes de viajar a
un destino de otro «Adaptee»
estándar y PawerPlugC

guardarlos a mano plug(PowerPointC)

para el próximo
viaje a un país con
el mismo estándar.
PowerPointC

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Adapter/adapterFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 36/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Scenario (ej. 5) La cohesión de la La granularidad de la clase Scenario (ej. 5)


depende del número de aparatos eléctricos clase Scenario es depende del número de aparatos eléctricos
y del número de distintos estándares. más adecuada y del número de distintos estándares.
puesto que asume
Se calcula como el producto de 2 por el Se calcula como el producto de 2 por el
menos
número de estándares (ej. C y F, 2) menos 1 número de estándares (ej. C y F, 2) menos 1
responsabilidad,
más el número de aparatos eléctricos (ej. más el número de aparatos eléctricos (ej.
centrada en los
secador y maquinilla de afeitar, 2). secador y maquinilla de afeitar, 2).
aparatos eléctricos
Su resultado es de orden lineal, O(n). con solo los Su resultado es de orden lineal, O(n).
adaptadores
necesarios según
los países de
destino.

Intención Aplicabilidad

La intención de este patrón es Se quiere crear una clase reutilizable que coopere con clases no relacionadas o que
convertir la interfaz de una no han sido previstas, es decir, clases que no tienen por qué tener interfaces
clase en otra interfaz que el compatibles.
cliente espera, permitiendo
Se quiere usar una clase existente (ej. una clase de una biblioteca que ha sido
trabajar clases conjuntamente
diseñada para reutilizarse) y su interfaz no concuerda con la que se
que no podrían de otra
necesita (específica del dominio que requiere la aplicación).
manera por la
incompatibilidad de sus
interfaces.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 37/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Adapter de clases Adapter de Objetos

Scenario Scenario

main() main()

Target Adaptee Target

request() spesificRequest() request()

public request() { Adapter public request() { Adapter


this.spesificRequest(); this.adapteeRequest();
} request() } request()

Adaptee

spesificRequest()

Target: declara una interfaz específica del dominio que usa el cliente.

Adaptee: declara una interfaz existente que necesita ser adaptada.

Adapter: clase que adapta la interfaz de Adaptee a la interfaz de Target.

Scenario: colabora con objetos que se ajustan a la interfaz Target, y utiliza el Adapter para poder colaborar con objetos que
se ajusten a la interfaz Adaptee.

Implementación

Variaciones
Adapter de clases: adapta una clase Adaptee a Target, pero se refiere únicamente a una clase Adaptee concreta. Por tanto, un
Adapter de clases no nos servirá cuando lo que queremos es adaptar una clase y todas sus subclases.

En una implementación en C++ de un Adapter de clases, el Adapter debería heredar públicamente de Target y privadamente
de Adaptee. Así, Adapter sería un subtipo de Target , pero no de Adaptee.

Se precisa definir las correspondientes operaciones abstractas para la interfaz reducida de Adaptee.

Adapter de objetos: permite adaptar varias subclases Adaptee existentes, es decir, el Adaptee- en sí y todas sus subclases en
caso de que las tenga. En esta situación no resulta práctico adaptar su interfaz heredando de cada una de ellas. Un Adapter de
objetos puede adaptar la interfaz de su clase padre.

El cliente reenvía las peticiones para acceder a la estructura jerárquica a un objeto delegado.

El cliente puede usar una estrategia de adaptación diferente cambiando el objeto delegado.

Consecuencias

Ventajas Desventajas

Adapter de clases: Permite que Adapter redefina parte del comportamiento de


Adaptee, por ser Adapter una subclase de Adaptee. Introduce un solo objeto y no se
necesita ningún puntero de indirección adicional para obtener el objeto adaptado.

Adapter de objetos: Permite que un mismo Adapter funcione con muchos Adaptee,
es decir, con el Adaptee en sí y todas sus subclases, en caso de que las tenga. El
Adapter puede añadir funcionalidad a todos los Adaptee a la vez.

Una clase es más reutilizable cuando minimizamos las asunciones que deben hacer
otras clases para usarla. Al hacer la adaptación de interfaces en una clase estamos
eliminando la asunción de que otras clases ven la misma interfaz. Dicho de otro
modo, la adaptación de interfaces nos permite incorporar nuestra clase a
sistemas existentes que podrían esperar interfaces diferentes a la de la clase.

Los adaptadores difieren en la cantidad de trabajo necesaria para adaptar Adaptee a


la interfaz Target. Hay una amplia gama de tareas posibles, que van desde la
simple conversión de interfaces (ej. cambiar los nombres de las operaciones), a
implicar alguna tarea de encapsulación o modificación de los argumentos y de los
tipos de retorno, o incluso a permitir un conjunto completamente nuevo de
operaciones. La cantidad de trabajo que hace el Adapter depende de lo
parecida que sea la interfaz de Target a la de Adaptee.

Problemas de Diseño y Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 38/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Incapacidad para modificar las Principio


clases convenientemente Abierto/Cerrado

Bridge
Problema

Motivación

Un asesor se Scenario

responsabiliza de main()

asesorar mediante
informes que
Adviser
presentan
advise()
adecuadamente
análisis de grandes
volúmenes de datos CasualAdviser FormalAdviser

con distinto nivel advise() advise()

de detalle,
superficial o formal
CasualFinancialAdviser CasualTaxAdviser CasualLegalAdviser FormalFinancialAdviser FormalTaxAdviser FormalLegalAdviser
o …, sobre
advise() advise() advise() advise() adviser() advise()
distintas áreas,
económica o fiscal o
legal o … EconomyMinistry TaxMinistry LawMinistry

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevas áreas.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Bridge/bridgeWrong)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Scenario (ej. 6) La cohesión de la La granularidad de la clase Scenario (ej. 6)


depende del número de niveles de detalle y clase Scenario no es depende del número de niveles de detalle y
del número de áreas. adecuada puesto del número de áreas.
que asume varias
Se calcula como el producto del número de Se calcula como el producto del número de
responsabilidades
niveles de detalle (ej. casual y formal, 2) por niveles de detalle (ej. casual y formal, 2) por
dispares o que no
el número de áreas (ej. económica, fiscal y el número de áreas (ej. económica, fiscal y
le atañen, como
legal, 3). legal, 3).
presentar
Su resultado es de orden cuadrático, O(n2). adecuadamente el Su resultado es de orden cuadrático, O(n2).
análisis de la
obtención de los
datos sobre las
distintas áreas.

Además, la
cohesión se ve
también
perjudicada por la
falta de
centralización de
las distintas áreas,
que se encuentran
replicadas en la
jerarquía de
herencias paralela
existente en los
analistas.

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 39/117
19/1/2021 Patrones de Diseño

Si la Scenario

responsabilidad main()

de asesor incluye
únicamente la
«Abstraction» «Implementation»

presentación de public advise() {


analyst.analyze();
Adviser Analyst

la información
advise() analyze()

con distinto nivel


de detalle (casual, «RedefinedAbstractionA» «RedefinedAbstractionB» «ConcreteImplementationA» «ConcreteImplementationB» «ConcreteImplementationC»
CasualAdviser FormalAdviser FinancialAnalyst TaxAnalyst LegalAnalyst
formal, …) y otros, advise() advise() analyze() analyze() analyze()

analistas, se
responsabilizan
por separado de
EconomyMinistry TaxMinistry LawMinistry

cómo se obtiene la
información para
las distintas
áreas, ninguna
clase será compleja
y se evitará la
tendencia a crecer.

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Bridge/bridgeFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Scenario (ej. 5) La cohesión de la La granularidad de la clase Scenario (ej. 5)


depende del número de niveles de detalle y clase Scenario es depende del número de niveles de detalle y
del número de áreas. adecuada puesto del número de áreas.
que asume una
Se calcula como la suma del número de Se calcula como la suma del número de
única
niveles de detalle (ej. casual y formal, 2) niveles de detalle (ej. casual y formal, 2) más
responsabilidad,
más el número de áreas (ej. económica, el número de áreas (ej. económica, fiscal y
centrada en el nivel
fiscal y legal, 3). legal, 3).
de detalle y el tipo
Su resultado es de orden lineal, O(n). área, colaborando Su resultado es de orden lineal, O(n).
con el servicio del
asesor y analista.

Se consigue así una


centralización de
las distintas áreas
evitándose la
replicación de
código en
jerarquías de
herencias
paralelas.

Intención Aplicabilidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 40/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es Evitar una relación estática entre una abstracción y su implementación. Por
desacoplar una abstracción de ejemplo, cuando debe seleccionarse o cambiarse la implementación en tiempo de
su implementación de tal ejecución.
forma que las dos pueden
Permitir que tanto las abstracciones como sus implementaciones sean
variar independientemente.
extensibles mediante subclasificación. En este caso, el patrón Bridge permite
multiplexar las opciones para las diferentes abstracciones y sus implementaciones, y
extenderlas independientemente.

Evitar que los cambios en la implementación de una abstracción tengan un


impacto en los clientes. Es decir, evitar que su código necesite ser recompilado.

Evitar una proliferación de clases en una jerarquía de herencia paralela.

Compartir una implementación entre varios objetos (tal vez usando un contador


de referencias) y este hecho deba permanecer oculto al cliente.

Solución

Estructura General Participantes

Scenario
Abstraction: declara la interfaz
de la abstracción, pudiendo
main()
proporcionar un
comportamiento y una
public operation() { Abstraction Implementor
estructura estándar. Además,
impl.operationImpl();
contiene una referencia a un
} operation() operationImpl()
objeto de tipo Implementor, que
normalmente se fija por medio
de un método set o a través del
ConcreteImplementorA ConcreteImplementorB
RedefinedAbstractionB RedefinedAbstractionA
constructor.
operationImpl() operationImpl()

RefinedAbstraction: clase
derivada de Abstraction que
extiende su interfaz
proporcionando un
comportamiento adicional o
modificado.

Implementor: declara la interfaz de la implementación.

Esta interfaz no tiene por qué corresponderse exactamente con la de la abstracción. De hecho, suelen ser muy distintas,
proporcionando la interfaz Implementor operaciones abstractas primitivas que la interfaz Abstraction utiliza para
ofrecer operaciones de más alto nivel.

Es decir, todas las operaciones de las subclases de la abstracción se implementan en términos de operaciones abstractas
de la interfaz del implementador. Esto desacopla las abstracciones de las diferentes implementaciones específicas de
cada plataforma. Nos referimos a la relación entre la abstracción y la implementación como un puente, porque una
abstracción con su implementación, permitiendo que ambas varíen de forma independiente.

ConcreteImplementor: clase derivada de Implementor que redefine su implementación concreta.

Implementación

Variaciones
En situaciones en las que sólo hay una implementación no es necesario crear una clase abstracta Implementor. Éste es
un caso degenerado del patrón Bridge, cuando hay una relación uno-a-uno entre Abstraction e Implementor. Sin embargo, esta
separación sigue siendo útil cuando un cambio en la implementación de una clase no debe afectar a sus clientes existentes, es
decir, éstos no deberían ser recompilados, sólo enlazados.

Para la selección del objeto Implementor existen diversas alternativas:

Si Abstraction conoce a todas las clases ConcreteImplementor, puede crear una instancia de una de ellas en su
constructor; puede decidir de cuál basándose en los parámetros recibidos en él.

Otro enfoque consiste en elegir inicialmente una implementación predeterminada y cambiarla después en función de su
uso.

También es posible delegar totalmente la decisión en otro objeto. Por ejemplo, Abstract Factory sabe qué tipo de
objetos ConcreteImplementor crear para la plataforma en uso. Una ventaja es que Abstraction no está acoplada
directamente a ninguna de las clases Implementor.

Algunas clases de implementación, especialmente las clases sin estado (que no mantienen un estado interno), pueden ser
compartidas entre múltiples objetos de la aplicación.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 41/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

No une permanentemente una implementación a una interfaz, sino que la


implementación puede configurarse en tiempo de ejecución. Incluso es posible
que un objeto cambie su implementación en tiempo de ejecución.

El hecho de desacoplar Abstraction e Implementor también elimina de la


implementación dependencias de tiempo de compilación. Ahora, cambiar
una clase ya no requiere recompilar la clase Abstraction y sus clientes. Esta
propiedad es esencial cuando debemos asegurar la compatibilidad binaria entre
distintas versiones de una biblioteca de clases.

Se pueden extender las jerarquías de Abstraction y de Implementor de manera


independiente.

Se puede aislar a los clientes de los detalles de implementación, como el


comportamiento de objetos implementadores y el correspondiente mecanismo de
conteo de referencias (si existe).

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Poner a funcionar los mecanismos de Reusabilidad Dependencias de plataformas hardware Acoplamiento


reutilización (delegación) por o software
composición,
herencia y/o
parametrización

Dependencias de las representaciones o Acoplamiento


implementaciones de objetos

Fuerte acoplamiento Acoplamiento

Añadir funcionalidad mediante herencia Principio


Abierto/Cerrado

Composite
Problema

Motivación

En muchos juegos
Scenario
de mesa (trivial
pursuit, parchis, …)
main()
hay limitaciones en
el tablero para el
número máximo
de jugadores y,
cuando hay más Game

personas que este


play(person1, person2)
máximo, existe la play(person1, team1)
posibilidad de play(team1,person1)
play(team1, team2)
formar equipos
para que se
entretengan
todos.
public play() { Team
for each person in team {
person.play(); play()
} addPerson()
removePerson()
}
getTeamMembers()

Person

play()

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevos tipos de equipos.

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Composite/compositeWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 42/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Game (ej. 2) La cohesión de la La granularidad de la clase Game (ej. 4)


depende de la cantidad de distintos tipos de clase Game no es depende de la cantidad de métodos
equipos y personas. adecuada puesto requeridos para los distintos tipos de
que asume varias equipos y personas.
Se calcula como la suma de la cantidad de
responsabilidades
distintos tipos de personas (ej. Person, 1) Se calcula como las variaciones con
dispares o que no
más la cantidad de distintos tipos de repetición1 de la suma de la cantidad de
le atañen, como la
equipos (ej. Team, 1). distintos tipos de personas (ej. Person, 1)
gestión de los
más la cantidad de distintos tipos de
Su resultado es de orden lineal, O(n). distintos tipos de
equipos (ej. Team, 1) tomados de dos en
jugadores
dos, con la simplificación de que el método
(personas y de
play relativo a la responsabilidad de la clase
equipos).
Game admite solo 2 parámetros.
1
Nótese que las variaciones con repetición
de m elementos tomados de n en n da
lugar a los posibles grupos formados por n
elementos de manera que:

No entran todos los elementos si m> n. Sí


pueden entrar todos los elementos si m ⇐
n.

Sí importa el orden.

Sí se repiten los elementos.

La fórmula para este tipo de variaciones es


VR=m^n

Su resultado es de orden cuadrático, O(n 2).


image::GranularidadWrongComposite.png[]

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 43/117
19/1/2021 Patrones de Diseño

La solución más
Scenario
habitual es
nombrar un
main()
representante del
equipo y, de cara
al resto de
jugadores, se
«Director»
comporta como
Game
un único jugador.
Internamente el play(person1, person2)
play(person1, team1)
representante se play(team1,person1)
organizará play(team1, team2)
transparentemente
con el resto de
personas del equipo
para tomar «Component»
decisiones. Player

play()

«Composite»
public play() { Team
for each person in team {
person.play(); play()
} addPerson()
} removePerson()
getTeamMembers()

«Leaf»
Person

play()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Composite/compositeFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Game (ej. 1) La cohesión de la La granularidad de la clase Game (ej. 1)


depende de la cantidad de métodos clase Game es depende de un tipo de jugador (ej. Player,
requeridos para un único tipo de jugador adecuada puesto 1).
(ej. Player, 1). que asume una
Su resultado es de orden constante, O(1).
única
Su resultado es de orden constante, O(1).
responsabilidad,
centrada en la
gestión de los
jugadores sin
prestar atención a
su tipo.

Intención Aplicabilidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 44/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es Representar jerarquías de objetos parte-todo.


componer objetos en
Permitir que los clientes sean capaces de obviar las diferencias entre
estructuras arbóreas para
composiciones de objetos y los objetos individuales. Los clientes tratarán a todos
representar las jerarquías de
los objetos de la estructura compuesta de manera uniforme.
todo-parte y permitir a los
clientes tratar con objetos
individuales y objetos
compuestos uniformemente.

Solución

Estructura General Participantes

Component: declara la interfaz


Scenario
de los objetos de la composición,
proporcionando, si es posible,
main()
implementaciones
predeterminadas para las
operaciones comunes a las
clases Leaf y Composite.
Director

Component

operation()

public operation() { Composite


for each child in composite { Leaf
child.operation(); operation()
} addComponent(Component)
operation()
removeComponent(Component)
}
getChild(int)

Opcionalmente:

Declara una interfaz para acceder a sus componentes hijos y gestionarlos.

Define una interfaz para acceder al padre de un componente en la estructura recursiva y, si es necesario, la implementa.

Leaf: clase derivada de Component que define el comportamiento de los objetos primitivos de la composición. Las
clases Leaf no tienen hijos.

Composite: clase derivada de Component que define el comportamiento de los objetos que tienen hijos. Por lo tanto,
almacena los componentes hijos e implementa las operaciones relacionadas con ellos.

Muchos diseños especifican una ordenación de los hijos de Composite. Cuando la ordenación de los hijos es una cuestión a
tener en cuenta, se deben diseñar las interfaces de acceso y gestión de hijos cuidadosamente para controlar la secuencia.

Director: clase que manipula los objetos de la composición a través de la interfaz Component.

Implementación

Variaciones
La clase Composite siempre es responsable de implementar las operaciones añadir y eliminar para controlar sus hijos, pero
existen dos alternativas para definir la interfaz de gestión de los hijos. La decisión implica un equilibrio entre seguridad
y transparencia:

Definir la gestión de los hijos en la clase Composite nos proporciona seguridad, ya que cualquier intento de añadir o
eliminar objetos de las hojas será detectado en tiempo de compilación en un lenguaje estáticamente tipado. Pero perdemos
transparencia porque las hojas y los compuestos tienen interfaces diferentes.

Definir la interfaz de gestión de los hijos en la raíz de la jerarquía de clases, Component, nos da transparencia, puesto
que podemos tratar a todos los componentes de manera uniforme. Sin embargo, sacrifica la seguridad, ya que los clientes
pueden intentar hacer cosas sin sentido, como añadir y eliminar objetos de las hojas.

Esta implementación a veces entra en conflicto con el principio de diseño de jerarquías de clases que dice que una
clase debería definir operaciones que tienen sentido en sus subclases, ya que hay muchas operaciones permitidas por
Component que no parecen tener sentido en las clases Leaf.

Se debe tener en cuenta también que definir el conjunto de hijos como una variable de instancia de la clase
Component, en la que se declaren las operaciones de acceso y gestión de hijos, supone una penalización de espacio para
los objetos de la clase Leaf, ya que se está almacenando un puntero que nunca será utilizado por éstos puesto que las
hojas nunca tendrán hijos. Por lo tanto, esto sólo merece la pena si hay relativamente pocos hijos en la estructura

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 45/117
19/1/2021 Patrones de Diseño

A veces un poco de creatividad muestra cómo una operación que podría parecer que sólo tiene sentido en el caso
de los Composite puede implementarse para todos los Component, moviéndola a la clase Component. Por ejemplo, la
interfaz para acceder a los hijos es una parte fundamental de la clase Composite, pero no de la clase Leaf. Pero si vemos
a una clase Leaf como un Component para acceder a los hijos que nunca devuelve ningún hijo, las clases Leaf pueden
usar esa implementación predeterminada, y las clases Composite pueden redefinir la implementación para devolver sus
hijos.

Scenario

main()

Director

Component

operation()
addComponent(Component)
removeComponent(Component)
getChild(int)

public operation() { Composite


for each child in composite { Leaf
child.operation(); operation()
} addComponent(Component)
operation()
removeComponent(Component)
}
getChild(int)

En caso de definir una interfaz para acceder al padre de un componente en la estructura recursiva, se simplifica el
recorrido y la gestión de la estructura compuesta, ya que la referencia al padre facilita ascender por la estructura y borrar un
componente.

El lugar habitual donde definir la referencia al padre es en la clase Component. Las clases Leaf y Composite pueden
heredar la referencia y las operaciones que la gestionan.

Con referencias al padre, es esencial mantener el invariante de que todos los hijos de un compuesto tienen como padre al
compuesto que a su vez los tiene a ellos como hijos. El modo más fácil de garantizar esto es cambiar el padre de un
componente sólo cuando se añade o se elimina a éste de un compuesto.

Otra posible variante del patrón se da cuando se requiere compartir componentes, por ejemplo, para reducir los requisitos
de almacenamiento.

En caso de que se necesite mantener referencias explícitas al padre de cada componente, los hijos tendrían que
almacenar múltiples padres. Pero eso puede llevarnos a ambigüedades cuando se propaga una petición hacia arriba en la
estructura.

Para simplificar la compartición sería necesario adaptar el diseño para evitar guardar los padres. Esto es factible en casos
en los que los hijos puedan evitar enviar peticiones a sus padres externalizando parte de su estado, o todo.

Consecuencias

Ventajas Desventajas

Define jerarquías de clases formadas por objetos primitivos y compuestos. Los Puede hacer que un diseño sea
objetos primitivos pueden componerse en otros objetos más complejos, que a su vez demasiado general. La
pueden ser compuestos y así de manera recursiva. Allí donde el código espere un desventaja de facilitar añadir
objeto primitivo, también podrá recibir un objeto compuesto. nuevos componentes es que
hace más difícil restringir los
Los clientes pueden tratar uniformemente a las estructuras compuestas y a los
componentes de un compuesto.
objetos individuales. Los clientes normalmente no conocen (y no les debería
A veces se requiere que un
importar) si están tratando con una hoja o con un componente compuesto. Esto
compuesto sólo tenga ciertos
simplifica el código del cliente, puesto que evita tener que escribir funciones con
componentes. Con el patrón
instrucciones if anidadas en las clases que definen la composición
Composite, no podemos confiar
Facilita añadir nuevos tipos de componentes. Si se definen nuevas subclases en el sistema de tipos para
Composite o Leaf, éstas funcionarán automáticamente con las estructuras y el código que haga cumplir estas
cliente existentes. No hay que cambiar los clientes para las nuevas subclases de restricciones, por lo que es
Component. necesario realizar
comprobaciones en tiempo de
ejecución.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 46/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Encontrar objetos apropiados Cohesión Añadir funcionalidad mediante herencia Principio


Abierto/Cerrado

Especificar la Implementación de Implementación


Objetos

Relacionar Estructuras del Tiempo de Acoplamiento


Compilación y de Ejecución

Decorator
Problema

Motivación

Un maestro de
Scenario
repostería se
main()
responsabiliza de
elaborar postres
(_galletas
tradicionales, public prepareTradicionalCookies(ApprenticePastryChef) {
apprenticePastryChef.beat();
soufflé, …) para lo this.addBehaviourToBeatTraditionalCookies();
MasterPastryChef apprenticePastryChef.bake();
que bate y hornea
this.addStateToBakeTraditionalCookies();
con diversos prepareTradicionalCookies(ApprenticePastryChef) }
prepareSoufle(ApprenticePastryChef)
utensilios (horno, addBehaviourToBeatTradicionalCookies() public prepareSouffle(ApprenticePastryChef) {
addStateToBakeTraditionalCookies()
reloj, …) con addBehaviourToBeatSouffle()
apprenticePastryChef.beat();
addStateToBakeSouffle() this.addBehaviourToBeatSouffle();
diferentes apprenticePastryChef.bake();
this.addStateToBakeSouffle();
técnicas }
específicas
(cambios de ritmo,
cambios de
Clock
temperatura, …). ApprenticePastryChef Oven

En sus labores, se beat() setLastTimeUsage()


getCurrentDate()
calculateMinutesBetweenDates()
apoya en un bake() isReady()
setAlarmDelay()

aprendiz que sólo


sabe batir y
hornear como le
digan, al que debe
supervisar
constantemente, lo
cual disturba al
maestro para Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
investigar e surgen nuevos tipos de postres.
innovar._

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Decorator/decoratorWrongx)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 47/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase MasterPastryChef La cohesión de la La granularidad de la clase MasterPastryChef


(ej. 2) depende del aprendiz y de los clase (ej. 6) depende de la cantidad de métodos
distintos tipos de utensilios. MasterPastryChef requeridos para los distintos postres y las
no es adecuada distintas técnicas.
Se calcula como la suma de 1 del aprendiz
puesto que asume
(ej. 1) más la cantidad de distintos tipos de Se calcula como el producto de la cantidad
varias
utensilios (ej. Oven, Clock, 2). de distintos postres (ej. TraditionalCookies,
responsabilidades
Souffle, 2) por 1 más la cantidad de
Su resultado es de orden lineal, O(n). dispares o que no
distintos tipos de técnicas (ej. beat, bake, 2).
le atañen, como la
supervisión del Su resultado es de orden cuadrático, O(n 2).
aprendiz mientras
elabora los postres
con diversos
utensilios e
investiga e innova.

También interesa analizar otro aspecto relacionado con la granularidad, en este caso, en la clase Scenario, ya que es posible
que se desee elaborar cualquier combinación de los distintos postres.

Es decir, la granularidad de la clase Scenario medida como el número de llamadas a métodos de la clase MasterPastryChef en
función de la cantidad de distintos postres.

Se calcula como la suma del aprendiz (ej. ApprenticePastryChef) y las combinaciones2 de la cantidad de distintos postres
tomadas de n en n, variando n desde uno hasta el número de postres.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 48/117
19/1/2021 Patrones de Diseño

2
Nótese que las combinaciones de m elementos tomados de n en n (m >= n) da lugar a los posibles grupos formados por n
elementos de manera que:

No entran todos los elementos si m > n. Sí pueden entrar todos los elementos si m = n.

No importa el orden.

No se repiten los elementos.

La fórmula para este tipo de variaciones es Cm,n = m! / (n! * (m-n)! )

Intención

Una alternativa es Scenario

invertir en la main()

contratación de
oficiales de
«Director»
cocina específicos MasterPastryChef

que se preparePastries(PastryChef)

responsabilizan
de elaborar «Component»

postres (_galletas PastryChef

tradicionales,
beat()
bake()

soufflé, …)
supervisando al
«ConcreteComponent» «Decorator»
aprendiz y ApprenticePastryChef SkilledPastryChef public beat() {
pastryChef.beat();
permitiendo al beat()
bake()
beat()
bake()
}

maestro centrarse
en la
investigación e
«ConcreteDecoratorA» «ConcreteDecorateB»
public beat() { TraditionalSkilledPastryChef FrenhCuisineSkilledPastryChef public bake() {

innovación._ super.beat();
this.addBehaviourToBeatTraditionalCookies(); beat() beat()
super.bake();
this.addStateToBakeSouffle();
bake() bake()
} addBehaviourToBeatTraditionalCookies() addBehaviourToBeatSouffle() }
addStateToBakeTraditionalCookies() addStateToBakeSouffle()

Clock
Oven

getCurrentDate()
setLastTimeUsage()
calculateMinutesBetweenDates()
isReady()
setAlarmDelay()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Decorator/decoratorFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase MasterPastryChef La cohesión de la La granularidad de la clase MasterPastryChef


(ej. 1) depende del tipo del repostero (ej. clase (ej. 1) depende únicamente del tipo de
PastryChef, 1). MasterPastryChef repostero.
es adecuada puesto
Su resultado es de orden constante, O(1). Su resultado es de orden constante, O(1).
que asume una
única
responsabilidad,
centrada en
colaborar con los
oficiales de cocina
para investigar e
innovar.

También interesa analizar otro aspecto relacionado con la granularidad, en este caso, en la clase Scenario, ya que es posible
que se desee elaborar cualquier combinación de los distintos postres.

Es decir, la granularidad de la clase Scenario medida como el número de llamadas a métodos de la clase MasterPastryChef en
función de la cantidad de distintos postres.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 49/117
19/1/2021 Patrones de Diseño

Se calcula como la suma del aprendiz (ej. ApprenticePastryChef) y el método relativo a la responsabilidad de la clase (ej.
preparePastries).

Intención Aplicabilidad

La intención de este patrón es Añadir responsabilidades a objetos individuales en vez de a toda una clase, sin
agregar responsabilidades afectar a otros objetos.
adicionales a un objeto
Añadir responsabilidad que pueda ser retirada.
dinámicamente, proveyendo
una alternativa flexible a la Evitar la extensión mediante herencia cuando ésta no es viable debido a:
subclasificación para Existencia de un gran número de extensiones independientes, que
extender la funcionalidad. producirían una explosión de subclases para permitir todas las
combinaciones.

Necesidad de utilizar una clase cuya definición esté oculta o no esté


disponible para ser heredada.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 50/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Component: declara la interfaz


Scenario
de los objetos a los que se puede
añadir responsabilidades
main()
dinámicamente.

La existencia de esta clase


garantiza una interfaz
compatible entre los
Director
componentes y los
decoradores.

Es importante que esta clase


común se mantenga ligera; es
decir, debería centrarse en
Component public operation() {
component.operation(); definir una interfaz, no en
operation() } guardar datos. La definición
de cómo se representan los
datos debería delegarse a las
subclases. De no ser así, la
complejidad de la clase
ConcreteComponent Decorator
Component puede hacer que
operation() operation() los decoradores sean
demasiado pesados como
para usar un gran número de
ellos e incrementa la
probabilidad de que las
ConcreteDecoratorA ConcreteDecoratorB
subclases concretas estén
pagando por características
operation() operation()
addState() addBehaviour() que no necesitan.

public operation() { public operation() {


this.addState(); super.operation();
super.operation(); this.addBehaviour();
} }

ConcreteComponent: clase derivada de Component que define un objeto al que se pueden añadir responsabilidades
adicionales.

Decorator: clase derivada de Component, por lo que define una interfaz que se ajusta a la interfaz de ésta, de manera que
su presencia es transparente a sus clientes. Esta transparencia permite anidar decoradores recursivamente, consiguiéndose
así un número de responsabilidades añadidas. Además, define los comportamientos estándar que se esperan de todas las
clases ConcreteDecorator, tales como:

Mantener una referencia a un objeto Component, que podrá ser un objeto ConcreteComponent u otro Decorator.

Reenviar las peticiones al componente y realizar, opcionalmente, acciones adicionales antes o después del reenvío.

ConcreteDecorator: clase derivada de Decorator que añade alguna responsabilidad al componente. Un ConcreteDecorator
puede definir métodos adicionales y/o variables para ampliar al componente.

Implementación

Variaciones
Se puede prescindir de la clase abstracta Decorator cuando sólo se necesita añadir una responsabilidad. Esta situación
es habitual cuando se está utilizando una jerarquía de clases existente y no diseñando una nueva. En ese caso, se puede
trasladar la responsabilidad de Decorator relativa al reenvío de peticiones al componente a la clase ConcreteDecorator.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 51/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

El patrón Decorator ofrece una manera más flexible de añadir responsabilidades Un diseño que usa el patrón
a los objetos que la utilización de la herencia (múltiple) estática. Con los Decorator suele dar como
decoradores se pueden añadir y eliminar responsabilidades en tiempo de ejecución. resultado sistemas formados
Por el contrario, la herencia requiere crear una nueva clase para cada por muchos objetos pequeños
responsabilidad adicional. Esto da lugar a muchas clases diferentes e incrementa la muy parecidos. Los objetos sólo
complejidad de un sistema. Por otro lado, utilizar diferentes clases se diferencian en la forma en
ConcreteDecorator para una determinada clase ConcreteComponent permite mezclar que están interconectados, y no
responsabilidades. en su clase o en el valor de sus
variables. Aunque dichos
Ofrece un enfoque para añadir responsabilidades que consiste en pagar sólo
sistemas son fáciles de adaptar
por aquello que se necesita. En vez de intentar permitir todas las
por parte de quienes los
funcionalidades inimaginables en una clase compleja y adaptable, se puede
comprenden bien, pueden ser
definir una clase simple y añadir luego funcionalidad incrementalmente con objetos
difíciles de aprender y de
ConcreteDecorator. La funcionalidad puede obtenerse componiendo partes simples.
depurar.
Como resultado, una aplicación no necesita pagar por características que no usa.

También resulta sencillo definir nuevos tipos de ConcreteDecorator


independientemente de las clases de objetos de las que hereden, incluso para
extensiones que no hubieran sido previstas. Extender una clase compleja
tiende a exponer detalles no relacionados con las responsabilidades que se
están añadiendo.

Un decorador se comporta como un revestimiento transparente, lo cual permite


que los decoradores aparezcan en cualquier lugar en el que pueda ir un
componente. Pero desde el punto de vista de la identidad de un objeto, un
componente decorado no es idéntico al componente en sí. Por tanto, no deberíamos
apoyarnos en la identidad de objetos cuando se estén usando decoradores.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar interfaces de objetos Especificar Añadir funcionalidad mediante herencia Principio


interfaces de Abierto/Cerrado
objetos
Abstracción

Relacionar Estructuras del Tiempo de Acoplamiento Incapacidad para modificar las clases Principio
Compilación y de Ejecución convenientemente Abierto/Cerrado

Facade
Problema

Motivación

Una obra de Scenario

reforma de un main()

domicilio
conlleva que el
propietario realice public performAlteration() {
this.bank.arrangeLoan();
diversas tareas this.townHall.arrangeLicense();

burocráticas Owner brickLayer.takeDownWall();


...
(solicitar crédito en Owner(bank, townHall) electrician.installLigtingSystem();
performAlteration() plumber.installFixture();
el banco, solicitar ...
carpenter.installMolding();
licencia en el painter.applyPaint();
}
ayuntamiento, …) y,
en particular,
contratar a Carpenter Electrician Plumber Painter BrickLayer
Bank TownHall
diversos installWindow() installWiring() installPipes() removeOldPaint() takeDownWall()
arrangeLoan() arrangelicense()
installMolding() installLightingSystem() installFixtures() applyPaint() buildWall()
especialistas
(albañil, carpintero,
electricista,
fontanero, pintor,
…) y coordinarlos
a todos (tiempos,
retrasos, Esto es muy complejo y tiende a crecer a medida que surgen nuevos colaboradores
materiales, especialistas (experto en domótica, decorador, …).
precondiciones, …).

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Facade/facadeWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 52/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Owner (ej. 7) La cohesión de la La granularidad del método


depende del número de relaciones por clase Owner no es performAlteration de la clase Owner (ej. 7)
tareas burocráticas y contratación de adecuada puesto depende del número de relaciones por
especialistas. que asume varias tareas burocráticas y contratación de
responsabilidades especialistas.
Se calcula como la suma de la cantidad de
dispares o que no
relaciones burocráticas (ej. Bank y Se calcula como la suma de la cantidad de
le atañen, como la
TownHall, 2) más la cantidad de operaciones burocráticas (ej. Bank y
contratación de
contrataciones de especialistas (ej. TownHall, 2) más la cantidad de
todos y cada uno de
BrickLayer, Carpenter, …, 5). contrataciones con especialistas (ej.
los especialistas
BrickLayer y Carpenter, …, 5).
Su resultado es de orden lineal, O(n). necesarios para la
reforma del Su resultado es de orden lineal, O(n).
AcoplamientoWrongFacade domicilio.

AcoplamientoWrongFacade2

Intención

Una alternativa Scenario


más sencilla y que
main()
no tiende a crecer
es que el
propietario se
public performAlteration() {
centre en sus this.bank.arrangeLoan(); «Director»
Owner
this.townHall.arrangeLicense();
tareas y contrate
Owner(bank, townHall)
contractor.performAltration();
a un contratista }
performAlteration(Contractor)

para no interactuar
con el resto de
especialistas. public performAlteration() {
brickLayer.takeDownWall();
...
«Facade»
TownHall electrician.installLigtingSystem(); Bank
Contractor
plumber.installFixture();
arrangelicense() ... arrangeLoan()
performAlteration()
carpenter.installMolding();
painter.applyPaint();
}

«SubsystemClass» «SubsystemClass» «SubsystemClass» «SubsystemClass» «SubsystemClass»


BrickLayer Carpenter Electrician Plumber Painter

takeDownWall() installWindow() installWiring() installPipes() removeOldPaint()


buildWall() installMolding() installLightingSystem() installFixtures() applyPaint()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Facade/facadeFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 53/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Owner (ej. 3) La cohesión de la La granularidad del método


depende del número de relaciones por clase Owner es performAlteration de la clase Owner (ej. 3)
tareas burocráticas y del contratista. adecuada puesto depende del número de relaciones por
que asume una tareas burocráticas y del contratista.
Se calcula como la suma de la cantidad de
única
relaciones burocráticas (ej. Bank y Se calcula como la suma de la cantidad de
responsabilidad,
TownHall, 2) más un contratista (ej. operaciones burocráticas (ej. Bank y
centrada en la
Contractor, 1). TownHall, 2) más una contratación con el
reforma mediante
contratista (ej. Contractor, 1).
la contratación de
unos pocos Su resultado es de orden lineal, O(n).
Su resultado es de orden lineal, O(n).
servicios, sin entrar
en detalles.

Intención Aplicabilidad

La intención de este patrón es Simplificar el uso de sistemas complejos proporcionando una interfaz más
proveer de una interfaz sencilla sin eliminar las opciones avanzadas. De esta manera puede proveer una
unificada a un conjunto de vista simple por defecto que es suficiente para la mayoría de los clientes, y solo los
interfaces de un subsistema clientes que necesiten más particularizaciones necesitarán mirar tras la fachada.
definiendo una interfaz de
Reducir el acoplamiento entre los clientes y las implementaciones de las clases
más alto nivel que hace más
de un subsistema cuando hay muchas dependencias entre ambos. Al desacoplar
fácil de usar el subsistema.
el subsistema de los clientes y otros subsistemas, promociona la independencia del
subsistema y la portabilidad.

Organizar por capas los subsistemas. Permite definir un punto de entrada para
cada nivel de subsistema. Si los subsistemas son dependientes, se pueden simplificar
las dependencias entre ellos haciéndolos comunicarse entre sí solamente a través de
sus fachadas.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 54/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Facade: clase que delega las


Scenario
peticiones de los clientes en los
objetos SubsystemClass
main()
apropiados, ya que sabe qué
clases del subsistema son las
responsables ante una petición.

Director

Facade

SubsystemClass1 SubsystemClass2 SubsystemClassN

SubsystemClass: implementan la funcionalidad del subsistema y llevan a cabo las peticiones solicitadas por el objeto
Facade, aunque para ellas, el objeto Facade sólo será otro cliente más, al que no conocen y del que no tienen una referencia.

Implementación

Variaciones
Puede implementarse el Facade como una interfaz o una clase abstracta, lo cual permite reducir aún más el
acoplamiento entre los clientes y el subsistema, ya que los clientes podrán comunicarse con el subsistema a través de dicha
interfaz y, definir en un momento posterior, los detalles de la implementación de la fachada concreta que será utilizada para
interaccionar con las clases del subsistema.

Consecuencias

Ventajas Desventajas

Promueve un débil acoplamiento entre el subsistema y sus clientes:

Los subsistemas a menudo obtienen complejidad según evolucionan. La mayoría


de los patrones, cuando se aplican, provocan más clases más pequeñas. Esto
hace del subsistema más reusable y fácil de personalizar, pero también llega a
ser más duro de usar por los clientes que no necesiten particularizaciones.

Blinda a los clientes de componentes del subsistema, reduciendo así el número de


objetos con los que tratan y haciendo que el subsistema sea más fácil de usar.

La reducción de las dependencias de compilación es vital en grandes


sistemas de software.

Ayuda a la organización por capas de un sistema. Todos los subsistemas pueden


tener su propio Facade para reducir el acoplamiento entre ellos.

Simplifica el traslado de los sistemas a otras plataformas.

No impide que las aplicaciones utilicen clases del subsistema si lo precisan. De


este modo se puede elegir entre la facilidad de uso y la generalidad.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Tamaño Fuerte acoplamiento Acoplamiento

Flyweight
Problema

Motivación

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 55/117
19/1/2021 Patrones de Diseño

En un torneo de
Scenario
cartas se disputan
mil juegos, y cada
main()
juego se
responsabiliza de
crear las 52
cartas de la
baraja que CardGame
public getCard(Suit, Value) {
precisa, por lo return new StandardCard(suit, value);
getCard(Suit, Value) }
que se necesitará getCard()
almacenar una
gran cantidad de
objetos iguales, es
decir, 52.000 cartas
Card
(mil ases de picas,
mil reyes de
getSuit()
corazones, …) getValue()
isFacedUp()
aunque éstas sean
flip()
constantes y no
cambien.

WildCard
StandardCard
getCard()
getSuit() setCard()
getValue() getSuit()
getValue()

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Flyweight/ yWeightWrong)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase CardGame (ej. 3) La cohesión de la La granularidad de la clase CardGame (ej. 2)


depende del número de subclases de clase CardGame no depende de la cantidad de métodos
cartas. es adecuada puesto requeridos.
que asume varias
Se calcula como la suma de la clase Se calcula como la cantidad de métodos
responsabilidades
abstracta carta (ej. Card, 1) más el número relativos para la gestión de cartas (ej.
dispares o que no
de subclases (ej. StandardCard y WildCard, getCard con y sin parámetros, 2).
le atañen, como las
2).
reglas del juego y la Su resultado es de orden lineal, O(n.
Su resultado es de orden lineal, O(n). obtención de las
cartas (creación de
AcoplamientoWrongFlyweight
objetos).

AcoplamientoWrongFlyweight2

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 56/117
19/1/2021 Patrones de Diseño

Si la Scenario

responsabilidad main()

del juego incluye


únicamente la
solicitud de «Director»
CardGame
cartas, y otro, CardGame(CardFactory)

fábrica de cartas, getCard(Suit, Value)


getCard()
getCard(PlayingCard, PlayingCard)
se responsabiliza
por separado de
crear una única public getCard(Suit, Value) {
carta de cada PlayingCard
«FlyWeightFactory»
requestedCard = new StandardCard/suit, Value);
cardFound = tis.card.contains(requestedCard);
palo y valor para PlayingCrd(Card,boolean)
CardFactory if(!cardFound)
this.card.add(requestedCard);
getCard()
ser reutilizada isFacedUp()
flip()
getCard(Suit,Value) cardPosition = this.cards.indexOf(requestedCard);
return this.cards.get(cardPosition);
por todos los }

juegos, lo cual
reducirá el número
«FlyWeight»
de objetos Card

utilizados. getSuit()
getValue()

«UnsharedConcreteFlyweight»
«ConcreteFlyWeight» WildCard
StandardCard
getCard()
getSuit() setCard()
getValue() getSuit()
getValue()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Flyweight/ yWeightFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase CardGame (ej. 5) La cohesión de la La granularidad de la clase CardGame (ej. 3)


depende de la fábrica de cartas y del tipo y clase CardGame es depende de la cantidad de métodos
número de subclases de cartas. adecuada puesto requeridos.
que asume una
Se calcula como la suma de la factoría de Se calcula como la cantidad de métodos
única
cartas (ej. CardFactory, 1) más la clase que relativos para la gestión de cartas (ej.
responsabilidad,
almacena el estado extrínseco (ej. getCard con y sin parámetros y setCard, 3).
centrada en las
PlayingCard, 1) más la clase del tipo de
reglas del juego, Su resultado es de orden lineal, O(n).
carta (ej. Card, 1) más el número de
colaborando con
subclases (ej. StandardCard y WildCard, 2).
las cartas
Su resultado es de orden lineal, O(n). suministradas por
la fábrica.

Intención Aplicabilidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 57/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es Aplicable cuando se cumplen todas las siguientes condiciones:
promocionar la compartición
Se utilizan un gran número de objetos idénticos o casi idénticos, existiendo un
para soportar un gran número
alto coste de almacenamiento debido a la gran cantidad de objetos.
de objetos de grano fino
eficientemente. Para todos aquellos objetos casi idénticos, las partes diferentes pueden ser
separadas de las partes similares, permitiendo la compartición de las partes
comunes.

El estado intrínseco consiste en la información que es independiente del


contexto, por lo que se puede compartir.

El estado extrínseco depende y varía con el contexto, por lo que no puede


ser compartido. Los clientes son responsables de la transmisión del estado
extrínseco cuando éste sea necesario.

Muchos grupos de objetos pueden ser reemplazados por relativamente


pocos objetos compartidos una vez que se elimina el estado extrínseco.

La extracción del estado extrínseco no ayudará a reducir los costos de


almacenamiento si hay muchos tipos diferentes de estado extrínseco.
Idealmente, el estado extrínseco puede ser calculado a partir de una estructura
de objetos separada, con un requisito de almacenamiento mucho más
pequeño.

La aplicación no depende de la identidad de un objeto. Dado que los objetos


pueden ser compartidos, las comprobaciones de identidad devolverán cierto para
objetos conceptualmente distintos.

Solución

Estructura General Participantes

Scenario FlyWeight: declara una clase


main()
abstracta o interfaz a través de
la cual los pesos ligeros pueden
recibir un estado extrínseco y
Director actuar sobre él.

public getFlyweight() {
if (flyWeight(key) != null)
return flyWeight(key)
FlyWeightFactory FlyWeight
else
newFlyWeight = new ConcreteFlyWeight();
flyWeightPool.add(newFlyWeight); getFlyWeight(key) operation(extrinsicState)
return newFlyWeight;
}

ConcreteFlyWeight UnshredConcreteFlyWeight

intrinsicState allState
operation(extrinsicState) operation(extrinsicState)

ConcreteFlyWeight: clase derivada de FlyWeight que implementa los métodos de la interfaz y permite almacenar el estado
intrínseco, en caso de que lo haya. Un objeto ConcreteFlyWeight debe poder ser compartido, por lo que cualquier estado que
almacene debe ser independiente del contexto del objeto concreto. Es decir, un objeto ConcreteFlyWeight no puede hacer
suposiciones sobre el contexto en el que opera.

UnsharedConcreteFlyWeight: no todas las subclases de FlyWeight necesitan ser compartidas, ya que la interfaz FlyWeight
permite la compartición, pero no fuerza a ella. Los objetos UnsharedConcreteFlyWeight suelen tener objetos
ConcreteFlyWeight como hijos en algún nivel de la estructura de objetos.

FlyWeightFactory: clase para la creación y el control de los objetos ConcreteFlyWeight, que garantiza que éstos se
compartan de manera adecuada. Cuando se solicita un ConcreteFlyWeight, la clase FlyWeightFactory proporciona una
instancia concreta o crea una instancia nueva en caso de que no exista ninguna.

Habitualmente, la clase FlyWeightFactory utiliza un array asociativo por algún código para almacenar los objetos
ConcreteFlyWeight disponibles.

Esto implica algún tipo de recuento de referencias o recogida de basura para el almacenamiento de un peso mosca
cuando ya no es necesario. Sin embargo, si el número de pesos mosca es fijo y pequeño puede ser interesante
mantenerlos de forma permanente.

Director: clase que mantiene una referencia a los objetos FlyWeight y calcula o guarda el estado extrínseco de los mismos.

Implementación

Variaciones
No existen variaciones del patrón.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 58/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

Se consigue un ahorro de almacenamiento, cuyo volumen es una función de Puede introducir costes de
varios factores: la reducción en el número total de instancias lograda mediante la tiempo de ejecución asociados
compartición; la cantidad de estado intrínseco por objeto; y si el estado extrínseco se con la transferencia, búsqueda
calcula o se almacena. y/o computación del estado
extrínseco.
Este ahorro en el caso del torneo de cartas sería el siguiente:
El acoplamiento entre clases
Almacenamiento Wrong
empeora al introducirse nuevas
El número de objetos carta estándar en la clase Scenario (ej. 104) será el clases requeridas por el patrón
producto del número de juegos simultáneos (ej. 2) por el número de cartas para facilitar la compartición.
estándar (ej. StandardCard, 52). Su resultado es de orden cuadrático, O(n2).

Cada carta estándar almacena 3 atributos: suit, value e isFacedUp.

Almacenamiento Fine

El número de objetos carta estándar en la clase Scenario (ej. 52) será el número
de cartas estándar (ej. StandardCard, 52). Su resultado es de orden lineal, O(n).

Cada carta estándar almacena 2 atributos: suit y value.

Para almacenar el estado extrínseco de las cartas, el número de objetos en la


clase Scenario (ej. 104) será el producto del número de juegos simultáneos (ej.
2) por el número de cartas (ej. PlayingCard, 52). Su resultado es de orden
cuadrático, O(n2).

Cada objeto almacena 1 atributo: isFacedUp.

En la siguiente gráfica se compara el número de atributos que es necesario


almacenar en ambos casos:

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Granularidad

Proxy
Problema

Motivación

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 59/117
19/1/2021 Patrones de Diseño

Un jefe se
Scenario
responsabiliza de
atender las
main()
peticiones de sus
empleados,
concesión de
vacaciones, subidas
de sueldos, … pero Employee
Boss
puede necesitar
Employee(Boss)
ausentarse, en requestHolidays(Date, int)
answerHolidaysRequest(Date, int)
answerSalaryIncreaseRequest()
cuyo caso dejará requestSalaryIncrease()
answerDoctorAppointmentRequest()
requestDoctorAppointment()
desatendidas sus requestInvoiceRefund(int)
answerInvoiceRefundRequest(int)
responsabilidades.
Esto provoca una
dependencia
innecesaria en la
localización del jefe
para que todo siga
su curso.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Proxy/proxyWrong)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Employee (ej. 1) La cohesión de la La granularidad de la clase Employee (ej. 4)


depende del tipo del jefe (ej. Boss, 1). clase Employee es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume una
Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. requestHolidays, requestSalaryIncrease,
centrada en sus
requestDoctorAppointment y
responsabilidades.
requestInvoiceRefund, 4).

Su resultado es de orden lineal, O(n).

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 60/117
19/1/2021 Patrones de Diseño

Si se nombra a un
Scenario
representante en
ausencia del jefe
main()
para que centralice
las peticiones de los
empleados, y las
responda siguiendo
«Director»
las instrucciones del Employee
«Subject»
Boss
jefe, las
responsabilidades Employee(Boss)
answerHolidaysRequest(Date, int)
requestHolidays(Date, int)
del jefe no requestSalaryIncrease()
answerSalaryIncreaseRequest()
answerDoctorAppointmentRequest()
quedarán requestDoctorAppointment()
answerInvoiceRefundRequest(int)
requestInvoiceRefund(int)
desatendidas y se
conseguirá una
independencia de la
localización del jefe.
«Proxy» «RealSubject»
ProxyBoss RealBoss

answerHolidaysRequest(Date, int) answerHolidaysRequest(Date, int)


answrSalaryIncreaseRequest() answerSalaryIncreaseRequest()
answerDotorAppointmentRequest() answerDoctorAppointmentRequest()
answerInvoiceRefundRequest(int) answerInvoiceRefundRequest(int)

public answerHolidaysRequest(Date, int) {


...
realBoss.answerHolideysRequest(Data, int);
...
}

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Proxy/proxyFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Employee (ej. 1) La cohesión de la La granularidad de la clase Employee (ej. 4)


depende del tipo del jefe (ej. Boss, 1). clase Employee es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume una
Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. requestHolidays, requestSalaryIncrease,
centrada en sus
requestDoctorAppointment y
responsabilidades.
requestInvoiceRefund, 4).

Su resultado es de orden lineal, O(n).

Intención Aplicabilidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 61/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es Existe una necesidad de una referencia a un objeto más versátil o sofisticada
proporcionar un sustituto o que un simple puntero:
representante de otro objeto
Un Proxy virtual permite crear objetos costosos por encargo, para diferir todo
para controlar el acceso al
el coste de su creación e inicialización hasta que sea realmente necesario usarlo.
mismo.
Un Proxy remoto proporciona un representante local de un objeto situado en
otro espacio de direcciones.

Un Proxy de protección controla el acceso al objeto original, lo cual resulta


útil cuando los objetos deberían tener diferentes permisos de acceso.

Una referencia inteligente es un Proxy de un simple puntero que lleva a


cabo operaciones adicionales cuando se accede a un objeto: contar el número
de referencias para poder liberar el objeto si no existen referencias a él, cargar un
objeto en memoria cuando es referenciado por primera vez, comprobar que se
bloquea el objeto real antes de acceder a él para garantizar que no pueda ser
modificado por ningún otro objeto, …

Solución

Estructura General Participantes

Subject: declara una interfaz


Scenario
común para RealSubject y Proxy,
de modo que pueda utilizarse un
main()
Proxy en cualquier sitio en el
que se espere un RealSubject.

Subject
Director

request()

Proxy RealSubject

request() request()

public request() {
...
realSubject.request();
...
}

RealSubject: clase que implementa la interfaz Subject y define el objeto real representado por el objeto Proxy.

Proxy: clase que implementa la interfaz Subject y puede sustituir al objeto RealSubject, redirigiendo las llamadas de los
métodos a éste cuando sea apropiado.

Mantiene una referencia que le permite acceder a RealSubject.

Los Proxy virtuales pueden guardar información adicional sobre RealSubject, por lo que pueden retardar el acceso al
mismo cuando se recibe una petición.

Los Proxy remotos son responsables de codificar una petición para enviársela a RealSubject cuando éste se encuentra en
un espacio de direcciones diferente.

Los Proxy de protección comprueban que el Director tenga los permisos de acceso necesarios para realizar una petición
a RealSubject.

Implementación

Variaciones
Si una clase Proxy puede tratar con su sujeto sólo a través de una interfaz abstracta, no hay necesidad de hacer una clase
Proxy para cada clase RealSubject puesto que el Proxy puede tratar de manera uniforme a todas las clases RealSubject. Esta
variación no es posible cuando los objetos Proxy van a crear instancias de RealSubject, ya que en ese caso necesitan
conocer la clase concreta.

Para implementar algunos tipos de Proxy en los que éste se comporta igual que un puntero, se puede aprovechar en lenguajes
como C++ la posibilidad de sobrecarga del operador de acceso a miembros, lo cual permite realizar tareas adicionales
cada vez que se desreferencia un objeto. Esto no es posible cuando se necesita saber exactamente qué operación es llamada ya
que la sobrecarga el operador de acceso a miembros no permite hacer esta distinción.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 62/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

Introduce un nivel de indirección al acceder a un objeto, lo cual tiene muchos Un inconveniente potencial del
posibles usos dependiendo del tipo de Proxy: Proxy remoto es que, como el
cliente no sabe que está
En el caso del Proxy virtual permite diferir la creación del objeto real hasta que
trabajando sobre una red,
éste es necesario. Además, permite realizar optimizaciones sobre cuándo y cómo
podría no estar preparado para
crear el objeto real.
las penalizaciones de tiempo
En el caso del Proxy remoto permite ocultar el hecho de que el objeto real que puedan ocurrir.
reside en un espacio de direcciones diferente, es decir, se puede ocultar la red
al cliente.

En el caso del Proxy de protección se puede establecer el control de acceso y


realizar tareas de mantenimiento adicionales cuando se accede al objeto.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar interfaces de objetos Abstracción Dependencias de las representaciones o Acoplamiento


implementaciones de objetos

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 63/117
19/1/2021 Patrones de Diseño

Patrones de Comportamiento
Patrón

+ composición interaccones complejas


Patrón de Comportamiento
+ (algoritmos/procesos)
+ CC II MM O! SS en TV

Chain of Responsability Command Interpreter Iterator Mediator Mememto Observer State Strategy Template Method Visitor

Tienen que ver con algoritmos y con la asignación de Encapsular aquello que puede variar es el tema de
responsabilidades a objetos para describir el flujo de muchos patrones de comportamiento. Cuando un
control complejo que es difícil de seguir en tiempo de determinado aspecto de un programa cambia con
ejecución, lo que permite olvidarse de éste para frecuencia, estos patrones definen un objeto que
concentrarse simplemente en el modo en que encapsula dicho aspecto. La mayoría de los patrones
interconectan los objetos. tienen dos tipos de objetos: el nuevo objeto que encapsula
el aspecto y el objeto existente que usa el nuevo objeto
creado. Normalmente, si no fuera por el patrón, la
funcionalidad de los nuevos objetos sería una parte
integral de los existentes.

Chain of Responsibility
Problema

Motivación

Un alumno se Scenario

main()

responsabiliza de
interponer una public complainProfessorBehaviour() {
...

reclamación
if(!this.professor.handleComplainAboutExam()) {
Student
if(!this.subjectCoordinator.handleComplainAboutExam()) {
if(!this.dpartamentHeadMaster.handleComplainAboutExam()) {
complainAboutExam() if(!this.educationAffairsViceDean.handleComplainAboutExam()) {

cuando tiene
complainAboutDepartamentRule()
if(!this.dean.handleComplainAboutExam()) {
...
}

alguna queja,
sobre un examen o Profesor
StudentDefender DepartamentHeadMaster Dean
SubjectCoordinator
EducationAffairsViceDean Provost

una regla de un
handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam()
handleComplainAboutExam() handleComplainAboutExam()
handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule()

departamento o …,
pero dependiendo
del tipo de
reclamación,
deberá conocer y
discernir a qué
miembro de la
cadena de
responsabilidad
debe presentar la
reclamación,
profesor o
coordinador de la
asignatura o
Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
director de
surgen nuevos miembros de la cadena de responsabilidad.
departamento o jefe
de estudios o
director de escuela
o rector o defensor
del alumno …

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/ChainOfResponsibility/chainOfResponsibilityWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 64/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Student (ej. 7) La cohesión de la La granularidad de los métodos de la clase


depende del número de miembros de la clase Student no es Student (ej. 7) depende del número de
cadena de responsabilidad. adecuada puesto miembros de la cadena de
que asume varias responsabilidad.
Se calcula como la suma de las clases
responsabilidades
miembros de la cadena de Se calcula como la suma de los miembros
dispares o que no
responsabilidad (ej. Professor, de la cadena de responsabilidad (ej.
le atañen, como
SubjectCoordinator, DepartmentHeadMaster, Professor, SubjectCoordinator,
discernir a qué
…, 7). DepartmentHeadMaster, …, 7).
miembro de la
Su resultado es de orden lineal, O(n). cadena de Su resultado es de orden lineal, O(n).
responsabilidad
debe presentar
cada reclamación.

Intención

Si la Scenario

main()

responsabilidad
de estudiante public complainAboutExam() {
...
«Director»
Student
«Handler»
ClaimSolver
claimSolver.handleComplainAboutExam();

incluye }
... complainAboutExam()
complainAboutDepartamentRule()
handleComplainAboutExam()
handleComplainAboutDepartamentRule()

únicamente la
interposición de
«ConcreteHandlerC» «ConcreteHandlerE» «ConcreteHandlerG» «ConcreteHandlerD» «ConcreteHandlerF»
«ConcreteHandlerB» «ConcreteHandlerA»
DepartamentHeadMaster Dean StudentDefender EducationAffairsViceDean Provost
SubjectCoordinator Profesor

handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam() handleComplainAboutExam()

la reclamación
handleComplainAboutExam() handleConplainAboutExam()
handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule() handleComplainAboutDepartamentRule()

ante el primer
miembro de la
cadena de
responsabilidad y
otros, miembros
de la cadena, se
responsabilizan
por separado de
elevar la
reclamación al
siguiente
miembro de la
cadena cuando no
pueden/saben
resolverla,
ninguna clase será
compleja y se
evitará la tendencia
a crecer.

Código de Ejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/ChainOfResponsibility/chainOfResponsibilityFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 65/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Student (ej. 1) La cohesión de la -La granularidad de los métodos de la clase
depende del tipo de la clase resolutora (ej. clase Student es Student (ej. 1) depende del tipo de la clase
ClaimSolver, 1). adecuada puesto resolutora (ej. ClaimSolver, 1).
que asume una
Su resultado es de orden constante, O(1).
única Su resultado es de orden constante, O(1).
responsabilidad,
centrada en la
interposición de la
reclamación,
colaborando
únicamente con el
servicio del primer
miembro de la
cadena de
responsabilidad,
que a su vez se
apoyará en el
servicio prestado
por el resto de
miembros de la
cadena para elevar
la reclamación
cuando sea preciso.

Intención Aplicabilidad

La intención de este patrón es Hay más de un objeto que puede manejar una petición y el manejador no se
evitar acoplar al emisor de conoce a priori, sino que debería determinarse automáticamente.
una petición a su receptor,
Se quiere enviar una petición a un objeto entre varios sin especificar
dando a más de un objeto la
explícitamente el receptor.
posibilidad de responder la
petición. Se basa en El conjunto de objetos que pueden tratar una petición debería ser
encadenar los objetos especificado dinámicamente.
receptores y pasar la petición
a lo largo de la cadena hasta
que es procesada por algún
objeto.

Solución

Estructura General Participantes

Handler: define una interfaz


Scenario
para tratar las peticiones.
main()
Opcionalmente implementa
el enlace al sucesor.

ConcreteHandler: clase
public handleRequest() {
derivada de Handler que trata
if(can handle)
Director
Handler
handlerMethod(); las peticiones de las que es
else responsable. Si puede manejar
handleRequest() successor.handlerequest();
} la petición, lo hace; en caso
contrario, la reenvía a su
sucesor.

ConcreteHandlerA ConcreteHandlerB

handleRequest() handleRequest()

Director: clase que inicia la petición a un objeto _ConcreteHandler- de la cadena, habitualmente, el primero.

No tiene conocimiento explícito de quién tratará la petición – se dice que la petición tiene un receptor implícito.

Implementación

Variaciones

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 66/117
19/1/2021 Patrones de Diseño

Para reenviar la petición a lo largo de la cadena, y para garantizar que los receptores permanecen implícitos, cada objeto de
la cadena comparte una interfaz común para procesar peticiones y para acceder a su sucesor en la cadena.

Hay dos formas de implementar la cadena sucesora:

Utilizar referencias a objetos existentes. Por ejemplo, las referencias al padre en una jerarquía de parte-todo pueden
definir el sucesor de una parte. Usar los enlaces existentes es posible cuando éstos permiten la cadena que necesitamos. Nos
evita tener que definir explícitamente nuevos enlaces y ahorra espacio.

Definir nuevos enlaces. Si no hay referencias preexistentes para definir una cadena, o los que existen no reflejan la cadena
de responsabilidad que necesita nuestra aplicación, habrá que definir enlaces nuevos. En este caso, Handler no sólo
define la interfaz para las peticiones, sino que normalmente también se encarga de mantener el sucesor. Eso
permite que Handler proporcione una implementación predeterminada de handleRequest que reenvíe la petición al
sucesor (si hay alguno). Si una subclase de ConcreteHandler no está interesada en dicha petición, no tiene que redefinir la
operación de reenvío, puesto que la implementación predeterminada la reenvía incondicionalmente.

Hay varias opciones para representar las peticiones:

En su forma más simple, una petición es una invocación a una operación insertada en el código. Esto resulta
conveniente y seguro, pero entonces sólo se pueden reenviar el conjunto prefijado de peticiones que define la clase Handler.

Una alternativa más flexible consiste en usar una única función handleRequest que reciba un código de petición
como parámetro, lo cual permite un número arbitrario de peticiones. Pero requiere que el emisor y el receptor se pongan
de acuerdo sobre cómo debe codificarse la petición y se necesitan sentencias condicionales para despachar la petición en
función de su código. Uno de los principales inconvenientes de este enfoque es que no hay un modo seguro de pasar los
parámetros con respecto al tipo, por lo que éstos deben ser empaquetados y desempaquetados manualmente.

Una alternativa para resolver el problema del paso de parámetros consiste en utilizar objetos aparte para las peticiones que
empaqueten los parámetros de la petición. Una clase Petición puede representar peticiones explícitamente, y se pueden
definir nuevos tipos de peticiones mediante herencia. Las subclases pueden definir diferentes parámetros. Los manejadores
deben conocer el tipo de petición para acceder a estos parámetros.

Consecuencias

Ventajas Desventajas

Libera a un objeto de tener que saber qué otro objeto maneja una petición. Un Dado que las peticiones no
objeto sólo tiene que saber que una petición será manejada “de forma apropiada”. tienen un receptor explícito, no
Ni el receptor ni el emisor se conocen explícitamente entre ellos, y un objeto de la hay garantía de que sean
cadena tampoco tiene que conocer la estructura de ésta. manejadas ya que la petición
puede alcanzar el final de la
Como resultado, se puede simplificar las interconexiones entre objetos. En
cadena sin haber sido
vez de que los objetos mantengan referencias a todos los posibles receptores, solo
procesada.
tienen una única interfaz a su sucesor.
En caso de haber un gran
Ofrece una flexibilidad añadida para repartir responsabilidades entre objetos.
número de mensajes y muchas
Se pueden añadir o cambiar responsabilidades para tratar una petición
etapas de redireccionamiento
modificando la cadena en tiempo de ejecución. Esto se puede combinar con la
en la cadena, podría tener lugar
herencia para especializar los manejadores estáticamente.
un alto intercambio baldío de
mensajes, por lo que el
rendimiento del sistema
podría degradarse.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar la Implementación de Implementación Dependencias de operaciones concretas Acoplamiento


Objetos

Relacionar Estructuras del Tiempo de Acoplamiento Fuerte acoplamiento Acoplamiento


Compilación y de Ejecución

Poner a funcionar los mecanismos de Reusabilidad por Añadir funcionalidad mediante herencia Principio
reutilización composición, Abierto/Cerrado
herencia y/o
parametrización

Command
Problema

Motivación

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 67/117
19/1/2021 Patrones de Diseño

En un restaurante
Scenario
hay distintos tipos
de empleados: main()
camareros,
cocineros,
bármanes, … Un
camarero se Restaurant
responsabiliza de
atender las attendToCustumersAtLunchTime()
attendToCustomersAtDinnerTime()
comandas de un
cliente con el
mismo algoritmo,
informar al cliente
Waiter Chef
de las opciones
Barman
disponibles en la Waiter(Chef, Barman) preparateSalad()
serveDishOfTheDay() preparateEggs()
carta y sus prepareVermouth()
serveConbinationPlate() preparateFries()
prepareBloodyMary()
ingredientes, anotar serveVermouth() preparateSoup()
cleanBar()
serveBloodyMary() preparateSteak()
la comanda, generateRandomEmployeeld() clanKitchen()
dirigirse al interior
(a la cocina o a la
barra o …) para
encargar la public serveDishOfTheDay() {
comanda al ...
int chefid = this.generateRandomEmployeeld();
empleado adecuado
this.chefs[chefid].prepareSoup();
(que sepa this.chefs[chefid].prepareSteak();
prepararla o …), this.chefs[chefid].prepareFries();
...
esperar a que
}
prepare la
comanda, servir la
comanda al cliente,
… pero
dependiendo de la
opción de la carta
seleccionada por
el cliente,
solicitará
distintas
preparaciones a
distintos tipos de
empleado, Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
cocinero o surgen nuevas opciones en la carta.
barman o …

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Command/commandWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 68/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Waiter (ej. 2) La cohesión de la La granularidad de la clase Waiter (ej. 5)


depende del número de tipos de empleados clase Waiter no es depende de la cantidad de métodos
encargados de preparar comandas. adecuada puesto requeridos para las distintas opciones de la
que asume varias carta.
Se calcula como la suma del número de
responsabilidades
tipos de empleados encargados de Se calcula como la suma de los métodos
dispares o que no
preparar comandas (ej. Chef y Barman, 2). relativos a la responsabilidad de la clase
le atañen, como la
para las distintas opciones de la carta (ej.
Su resultado es de orden lineal, O(n). localización del
serveDishOfTheDay, serveCombinationPlate,
tipo de empleado
serveVermouth y serveBloodyMary, 4) más la
adecuado para
localización del empleado encargado de
preparar la
preparar cada comanda
comanda y las
(generateRandomEmployeeId, 1).
preparaciones
necesarias para Su resultado es de orden lineal, O(n).
cada opción de la
carta.

Intención

Si la Scenario

responsabilidad main()

de camarero
incluye «Director»
Restaurant

únicamente la attendToCustumersAtLunchTime()
attendToCustomersAtDinnerTime()

colocación de la
comanda en un «Invoker»
«Command»
public serve() { Order
lugar acordado y
Waiter
order.serve();
} serve()
serve(Order)
generateRandomNumber()
la posterior
recogida de la
«AbstractCommandA» «AbstractCommandB»
comanda ChefOrder BarmanOrder

preparada para
ChefOrder(Cheef) BarmanOrder(Barman)
getChef() getBarman()

servírsela al
cliente, y otros, «Receiver»
Chef «Receiver»
«ConcreteCommandAA» «ConcreteCommandAB» «ConcreteCommandBB» «ConcreteCommandBA»
cocineros y preparateSalad() DishOfTheDayOrder CombinationPlateOrder BloodyMaryOrder VermouthOrder
Barman

preparateEggs()
prepareVermouth()
bármanes, se
preparateFries() DishOfTheDayOrder(Chef) CombinationPlateOrder(Chef) BloodyMaryOrder(Barman) VermouthOrder(Barman)
prepareBloodyMary()
preparateSoup() serve() serve() serve() serve()
cleanBar()
preparateSteak()

responsabilizan
clanKitchen()

por separado de
escoger la
public serve() {
...
this.getChef().prepareSoup();
comanda que van this.getChef().prepareSteak();
this.getChef().prepareFries();
...
a preparar según }

sus condiciones y
dejarla
preparada en el
lugar acordado,
habrá dos equipos
de trabajo
independientes y
mucho menos
trabajo para el
camarero.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 69/117
19/1/2021 Patrones de Diseño

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Command/commandFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Waiter (ej. 1) La cohesión de la La granularidad de la clase Waiter (ej. 1)


depende del tipo de la comanda (ej. Order, clase Waiter es depende del tipo de la comanda.
1). adecuada puesto
Se calcula como la suma de los métodos
que asume una
Su resultado es de orden constante, O(1). relativos a la responsabilidad de la clase
única
(ej. serve, 1).
responsabilidad,
centrada en la Su resultado es de orden constante, O(1).
gestión de las
comandas de cara
al cliente,
colaborando con el
servicio del
cocinero/barman.

Intención Aplicabilidad

La intención de este patrón es Parametrizar objetos con una acción a realizar. Los objetos Command son un
encapsular una petición como sustituto orientado a objetos para las funciones callback.
un objeto, permitiendo de ese
Especificar, poner en cola y ejecutar peticiones en diferentes instantes del
modo parametrizar clientes
tiempo. Un objeto Command puede tener un tiempo de vida independiente de la
con diferentes peticiones,
petición original. Si se puede representar el receptor de una petición en una forma
colas o solicitudes registradas,
independiente del espacio de direcciones, entonces se puede transferir un objeto
y apoyar las operaciones de
Command con la petición a un proceso diferente y llevar a cabo la petición allí,
deshacer.
desacoplando la fuente de una petición del objeto que la cumple.

Permitir deshacer. La operación execute de Command puede guardar en el propio


comando el estado que anule sus efectos. Debe añadirse a la interfaz Command una
operación undo que anule los efectos de una llamada anterior a execute. Los
comandos ejecutados se guardan en una lista que hace las veces de historial. Se
pueden lograr niveles ilimitados de deshacer y repetir recorriendo dicha lista hacia
atrás y hacia adelante llamando respectivamente a las operaciones undo y execute.

Permitir registrar los cambios de manera que se puedan volver a aplicar en


caso de caída del sistema. Aumentando la interfaz de Command con operaciones
para cargar y guardar se puede mantener un registro persistente de los cambios.
Recuperarse de una caída implica volver a cargar desde el disco los comandos
guardados y volver a ejecutarlas con la operación execute.

Estructurar un sistema alrededor de operaciones de alto nivel construidas


sobre operaciones básicas. Esta estructura es común en los sistemas de
información que permiten transacciones, que encapsulan un conjunto de cambios
sobre unos datos. El patrón Command ofrece un modo de modelar transacciones.
Los comandos tienen una interfaz común, permitiendo así invocar a todas las
transacciones del mismo modo. El patrón también facilita extender el sistema con
nuevas transacciones.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 70/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Command: declara una interfaz


Scenario
para ejecutar una operación.

main() ConcreteCommand: clase


derivada de Command que
define un enlace a un objeto
Receiver, y que implementa el
método para ejecutar una
Director
operación de la interfaz
Command invocando la
correspondiente operación u
operaciones de Receiver.

Receiver
Command
Invoker
action1()
execute()
action2()

ConcreteCommandA ConcreteCommandB

execute() execute()

public execute() { public execute() {


... ...
receiver.action1() receiver.action2()
... ...
} }

Director: clase que crea un objeto ConcreteCommand y establece su Receiver.

Invoker: clase que solicita a través de la interfaz Command que se ejecute la operación.

Receiver: clase que sabe cómo llevar a cabo las operaciones asociadas a una petición.

Implementación

Variaciones
Un comando puede tener un rango diverso de habilidades:

Se puede limitar a definir un enlace entre un receptor y las acciones que lleva a cabo la petición.

Se puede ocupar de implementar todas las acciones ella misma sin delegar para nada en el receptor. Este último
extremo resulta útil cuando queremos definir comandos que sean independientes de las clases existentes, cuando no existe
ningún receptor adecuado o cuando un comando conoce implícitamente a su receptor.

En algún punto entre estos dos extremos se encuentran los comandos que tienen el conocimiento suficiente para
encontrar dinámicamente sus receptores.

Los comandos pueden permitir capacidades de deshacer y repetir si proveen un modo de revertir su ejecución. Una
clase ConcreteCommand podría necesitar almacenar información de estado adicional para hacer esto. Este estado puede
incluir:

El objeto Receiver, el cual es quien realmente realiza las operaciones en respuesta a la petición;

Los argumentos de la operación llevada a cabo por Receiver; y

Cualquier valor original de Receiver que pueda cambiar como resultado de manejar la petición. El receptor debe
proporcionar operaciones que permitan al comando devolver el receptor a su estado anterior.

La histéresis (tendencia de un material a conservar una de sus propiedades, en ausencia del estímulo que la ha generado)
puede ser un problema a la hora de garantizar un mecanismo de deshacer/rehacer fiable, que preserve la semántica.
Los errores se pueden acumular a medida que se ejecutan y deshacen los comandos repetidamente, de manera que el
estado de una aplicación finalmente difiera de sus valores originales. Por tanto, puede ser necesario guardar más
información con el comando para asegurar que los objetos son devueltos a su estado original

Se pueden permitir diferentes niveles de deshacer/rehacer. Para permitir un nivel, sólo es necesario guardar el último
comando que se ejecutó. Para múltiples niveles es necesario guardar un historial de los comandos que han sido
ejecutados, donde la máxima longitud de la lista determina el número de niveles permitidos. Recorrer la lista hacia atrás
deshaciendo los comandos cancela sus efectos; recorrerla hacia delante ejecutando los comandos los rehace.

Un comando anulable puede que necesite ser copiada antes de ser guardada en el historial. Puesto que el objeto
Command que llevó a cabo la petición original más tarde ejecutará otras peticiones, la copia es necesaria para distinguir
entre diferentes invocaciones del mismo comando si su estado puede variar entre invocaciones sucesivas. En caso de que
el estado del comando no cambie tras su ejecución no es necesario realizar la copia, basta con guardar en el historial una
referencia al comando.

Se pueden ensamblar comandos en un comando compuesto (MacroCommand).

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 71/117
19/1/2021 Patrones de Diseño

Este tipo de comandos no tienen ningún receptor explícito, sino que son los comandos que contiene las que definen su
propio receptor.

Si el MacroCommand soporta la función deshacer, todos los comandos internos también deben soportarla. Cuando se
llama a la función para invertir el comando, esta llamada debe ser redirigida a los hijos en el orden inverso de la operación
execute.

Consecuencias

Ventajas Desventajas

Desacopla el objeto que invoca la operación de aquél que tiene el


conocimiento para ejecutarla.

Permite reemplazar objetos Command y Receiver en tiempo de ejecución.

Los comandos son objetos de primera clase. Pueden ser manipulados y


extendidos como cualquier otro objeto.

Es fácil añadir nuevos comandos, ya que no hay que cambiar las clases existentes.

Se pueden ensamblar comandos en un comando compuesto para ejecutar una


secuencia de comandos.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Tamaño Dependencias de operaciones concretas Acoplamiento

Especificar la Implementación de Objetos Implementación Fuerte acoplamiento Acoplamiento

Interpreter
Problema

Motivación

Un operador se
Scenario
responsabiliza de
main()
manejar un
aparato complejo
siguiendo una
serie de public performCompositeScriptForStarting(Machine machine) {
this.performOperation(machine, "A");
protocolos, this.performOperation(machine, "B");
this.performOperation(machine, "C");
protocolo de }
mañana o de tarde Operator

o …, los cuales public performIterativeScriptForTasksDE(Machine machine,int times) { performMorningProtocol(Machine)


for (int time = 0; < times; time++) {
constan de performEveningProtocol(Machine)
this.performOperation(machine, "D"); performCompositeScriptForStarting(Machine)
diversas this.performOperation(machine, "E"); performIterativeScriptForTasksDE(Machine, int)
performIterativeScriptForTasksF(Machine, int)
}
combinaciones de }
performIterativeScriptForTasksFED(Machine, int)
performCompositeScriptForSwitchingOff(Machine)
diversos tipos de performOperation(Macine, String)
...
operaciones
public performOperation(Machine machine, String name) {
simples y/o machine.execute(name);
compuestas, que }

debe saber
ejecutar
manualmente. Machine

execute(String)

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevos protocolos.

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Interpreter/interpreterWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 72/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Operator (ej. 1) La cohesión de la La granularidad de la clase Operator (ej. 8)


depende del tipo de la máquina (ej. clase Operator no depende de la cantidad de métodos
Machine, 1). es adecuada puesto requerido.
que asume varias
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
responsabilidades
relativos a la responsabilidad de la clase
dispares o que no
para los distintos tipos de protocolos (ej.
le atañen, como el
performMorningProtocol y
conocimiento y la
performEveningProtocol, 2) más el número
ejecución manual
de tipos de operaciones (simples y/o
de los diversos
compuestas) de las que constan (ej.
tipos de
performCompScriptForStarting,
operaciones
performIterScriptForTasksDE,
simples y/o
performIterScriptForTaskF,
compuestas.
performIterScriptForTasksFED,
performCompScriptForSwitchingOff y
performOperation, 6).

Su resultado es de orden lineal, O(n).

Intención

Si la Scenario

responsabilidad main()

de operador
incluye
«Director»
public performProtocol() {
únicamente la sript.execute(machine);
Operator

}
solicitud de performProtocol(Script, Machine)

ejecución
automática del «Context» «AbstractExpression»
Machine Script
protocolo
execute(String) execute(Machine)
(protocolo de
mañana, protocolo
de tarde, …) y otros, «TerminalExpression» «NonTerminalExpression» «NonTerminalExpression» public execute(Machine) {
OperationScript IterativeScript CompositeScript for (Script script : this.scripts) {
scripts, se OperationScript(String) IterativeScript(Script, int) addScript(Script) }
script.execute(machine);

responsabilizan
execute(Machine) execute(Machine) execute(Machine) }

por separado de
cómo se public execute(Machine) {
for (int times = 0; times<this.times; times++) {
interpretan los
public execute(Machine) { «NonTerminalExpression» «NonTerminalExpression»
machine.execute(this.name); this.script.execute(machine); MorningProtocolScript EveningProtocolScript
} }
protocolos en }

operaciones
simples y/o
compuestas,
ninguna clase será
compleja y se
evitará la tendencia
a crecer.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 73/117
19/1/2021 Patrones de Diseño

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Interpreter/interpreterFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Operator (ej. 2) La cohesión de la La granularidad de la clase Operator (ej. 1)


depende del tipo de la máquina (ej. clase Operator es depende del script.
Machine, 1) y del tipo del script (ej. Script, 1). adecuada puesto
Se calcula como la suma de los métodos
que asume una
Su resultado es de orden constante, O(1). relativos a la responsabilidad de la clase
única
(ej. performProtocol, 1).
responsabilidad,
centrada en la Su resultado es de orden constante, O(1).
ejecución manual
de los diversos
tipos de scripts.

Intención Aplicabilidad

La intención de este patrón es, Hay un lenguaje que interpretar y se pueden representar las sentencias del
dado un lenguaje, definir una lenguaje como árboles sintácticos abstractos.
representación de su
Hay un tipo de problemas que ocurren con cierta frecuencia, y es posible
gramática junto con un
expresar las apariciones de esos problemas como instrucciones de un lenguaje
intérprete que utiliza la
simple, para el cual se puede construir un intérprete que sea capaz de resolver estos
representación para
problemas mediante la interpretación de dichas instrucciones.
interpretar sentencias del
lenguaje. El patrón Interpreter funciona mejor cuando:

La gramática es simple. Para gramáticas complejas, la jerarquía de clases de la


gramática se vuelve grande e inmanejable. Herramientas como los generadores
de analizadores sintácticos constituyen una alternativa mejor en estos casos, ya
que pueden interpretar expresiones sin necesidad de construir árboles sintácticos
abstractos, lo que puede ahorrar espacio y, posiblemente, tiempo.

La eficiencia no es una preocupación crítica. Los intérpretes más eficientes


normalmente no se implementan interpretando árboles de análisis sintácticos
directamente, sino que primero los traducen a algún otro formato. Por ejemplo,
las expresiones regulares suelen transformarse en máquinas de estados. Pero
incluso en ese caso, el traductor puede implementarse con el patrón Interpreter,
de modo que éste sigue siendo aplicable.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 74/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

AbstractExpression: declara la
Scenario
interfaz para interpretar, que es
común a todos los nodos del
main()
árbol sintáctico abstracto.

Director

AbstractExpression
Contex

interpret(Context)

TerminalExpression NonTerminalExpression

interpret(Context) interpret(Context)

TerminalExpression: clase derivada de AbstractExpression que implementa la interfaz para interpretar asociada con los
símbolos terminales de la gramática.

Se necesita una instancia de esta clase para cada símbolo terminal de una expresión.

NonTerminalExpression: clase derivada de AbstractExpression que define el comportamiento de los objetos asociados con
los símbolos no terminales de la gramática, es decir, para las reglas de la gramática, que pueden estar formadas a su vez
por otras reglas o por expresiones terminales.

Se necesita una instancia de esta clase para cada regla de la gramática.

Mantiene variables de instancia de tipo AbstractExpression para cada uno de los símbolos que contiene la regla que
representa.

Implementa la interfaz para interpretar asociada con los símbolos no terminales de la gramática. Normalmente, esta
implementación consiste en llamarse a sí misma recursivamente sobre las variables de instancia que representa.

Context: clase que contiene la información que es global al intérprete.

Director: clase que construye o recibe un árbol sintáctico abstracto que representa una determinada sentencia del
lenguaje definido por la gramática, y que invoca a la operación de interpretar con el contexto adecuado.

Implementación

Variaciones
El patrón Interpreter no especifica cómo crear un árbol sintáctico abstracto ni se ocupa de llevar a cabo el análisis
sintáctico. El árbol sintáctico abstracto puede ser creado mediante un analizador sintáctico dirigido por una tabla, mediante
un analizador sintáctico (normalmente recursivo descendente) hecho a mano o directamente por el Director.

En caso de que se vaya a crear un intérprete que realice múltiples operaciones sobre los árboles sintácticos abstractos,
para evitar definir estas operaciones en cada clase de la gramática, será preferible utilizar el patrón Visitor.

En aquellas gramáticas cuyas sentencias tengan muchas repeticiones de uno o varios símbolos terminales, puede ser
beneficioso compartir una única copia de dichos símbolos. Las gramáticas de los programas software son buenos ejemplos
de ello.

Los nodos terminales generalmente no guardan información sobre su posición en el árbol sintáctico abstracto.

Los nodos padre les pasan cualquier información de contexto que necesiten para llevar a cabo la interpretación,
incluida su posición en el árbol sintáctico abstracto.

Por tanto, se da una distinción entre estado compartido (intrínseco) y estado recibido (extrínseco), que permite utilizar el
patrón FlyWeight.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 75/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

El uso de clases para representar las reglas de la gramática facilita realizar Las gramáticas complejas con
cambios o extensiones de ésta mediante herencia. Esto permite modificar muchas reglas son difíciles de
incrementalmente las expresiones existentes y definir otras nuevas como mantener, ya que el patrón
variaciones de las antiguas. Interpreter define al menos una
clase para cada regla de la
Permite incluir nuevos métodos en la interfaz Expression para añadir nuevas
gramática (las reglas que se
maneras de interpretar expresiones aumentando la funcionalidad. Para
hayan definido usando BNF3
conseguir mayor flexibilidad sin afectar las clases de la gramática se recomienda
pueden necesitar varias clases).
considerar la utilización del patrón Visitor.
Cuando se da esta circunstancia,
se pueden aplicar otros patrones
de diseño para mitigar el
problema, pero se recomienda
considerar el uso de otras
técnicas más adecuadas como
los generadores de
analizadores sintácticos o de
compiladores.
3 La notación de Backus-Naur,
también conocida por sus
denominaciones inglesas
Backus-Naur form (BNF),
Backus-Naur formalism o
Backus normal form, es un
metalenguaje usado para
expresar gramáticas libres de
contexto.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Iterator
Problema

Motivación

Un cliente se Scenario
responsabiliza de
main()
comprar muebles
para una
estancia,
dormitorio o jardín Customer

…, en distintas buyRoomFurnitureIntoRoomOrganizedFurnitureStore(FurnitureStore, Room)


buyRoomFurnitureIntoSizeOrganizedFurnitureStore(FurnitureStore, Room)
tiendas de discoverFurnitureStoreFloors(FurnitureStore)
nextProductRoomOrganizedFurnitureStore(Room)
muebles, las hasMoreProductsInRoomOrganizedFurnitureStore(Room)
nextProductInSizeOrganizedFurnitureStore(FurnitureStore, Room)
cuales tienen hasMoreProductsInSizeOrganizedFurnitureStore(FurnitureStore, Room)

distintos criterios
de organización
de sus plantas, FurnitureStore
por estancia de la
addFloor(Floor)
casa o por tamaño distributeFurnitureInFloors()
getFloors()
de los muebles o … getFurniture()

Para ello, el cliente


debe averiguar
cuál es el criterio Furniture Floor
RoomOrganizedFurnitureStore SizeOrganizedFurnitureStore
de organización y getName() addFurniture(Furniture)
ser capaz de getRoom()
getSize()
getFurniture()
getFurnitureType()
distributeFurnitureInFloors() distributeFurnitureInFloors()

localizar los
muebles para la
estancia que le Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
interesa. surgen nuevos criterios de organización.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Iterator/iteratorWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 76/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Customer (ej. 3) La cohesión de la La granularidad de la clase Customer (ej. 7)


depende de del tipo de tienda de muebles y clase Customer no depende de la cantidad de métodos
de sus características. es adecuada puesto requeridos.
que asume varias
Se calcula como la suma de la tienda (ej. Se calcula como la suma de los métodos
responsabilidades
FurnitureStore, 1) más el tipo de plantas de relativos a la responsabilidad de la clase
dispares o que no
las que consta (ej. Floor, 1) y el tipo de para comprar muebles según el criterio de
le atañen, como el
productos que se venden en ella (ej. organización de cada tienda (ej.
conocimiento del
Furniture, 1). buyFurnitureIntoRoomOrganizedFurnitStore y
criterio de
buyFurnitureIntoSizeOrganizedFurnitStore, 2)
Su resultado es de orden constante, O(1). organización de la
más el número de tipos de operaciones
tienda y la
para localizar los muebles (ej.
localización de los
discoverFurnitStoreFloors,
muebles en las
nextProdInRoomOrganizStore,
distintas plantas.
hasMoreProdsInRoomOrganizStore,
nextProdInSizeOrganizStore y
hasMoreProdsInSizeOrganizStore, 5).

Su resultado es de orden lineal, O(n).

Intención

Si la Scenario

responsabilidad main()

de cliente incluye
únicamente la «Director»
Customer

solicitud de buyRoomFurniture(FurnitureStore, Room)

muebles para un
tipo de estancia y «Aggregate»
FurnitureStore
otros,
«Iterator»
ShopAssistant
addFloor(Floor)

dependientes, se
distributeFurnitureInFloors()
nextProduct()
getFloors()
hasMoreProducts()
getFurniture()

responsabilizan
createShopAssistant()

por separado de
conocer el criterio «ConcreteAggregateA»
RoomOrganizedFurnitureStore
«ConcreteAggregateB»
SizeOrganizedFurnitureStore
Furniture Floor «ConcreteIteratorA»
RoomOrganizedShopAssistant
«ConcreteIteratorB»
SizeOrganizedSopAssistant

de organización
getName() addFurniture(Furniture)
distributeFurmitureInFloors() distributeFurmitureInFloors() getRoom() getFurniture() nextProduct() nextProduct()
createShopAssistant() createShopAssistant() getSize() getFurnitureType() hasMoreProducts() hasMoreProducts()

de la tienda y de
localizar los
muebles, ninguna
clase será compleja
y se evitará la
tendencia a crecer.

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Iterator/iteratorFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 77/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Customer (ej. 2) La cohesión de la La granularidad de la clase Customer (ej. 1)


depende del tipo de la tienda de muebles clase Customer es depende de la cantidad de métodos
(ej. FurnitureStore, 1) y del tipo de adecuada puesto requeridos.
dependiente (ej. ShopAssistant, 1). que asume una
Se calcula como la suma de los métodos
única
Su resultado es de orden constante, O(1). relativos a la responsabilidad de la clase
responsabilidad,
(ej. buyRoomFurniture, 1).
centrada en
comprar muebles, Su resultado es de orden constante, O(1).
colaborando con el
servicio del
dependiente que
conoce el criterio
de organización de
la tienda y la
localización de los
muebles en las
distintas plantas.

Intención Aplicabilidad

La intención de este patrón es Acceder al contenido de un objeto agregado, tal como una lista, sin exponer su
proveer una forma de acceder representación interna.
secuencialmente a los
Permitir varias maneras de recorrer los elementos de los objetos agregados:
elementos de un objeto
agregado sin exponer su Pudiendo coexistir varios recorridos en espera sobre el mismo objeto
representación subyacente. agregado, llevados a cabo por el mismo o distintos clientes.

Sin afectar la interfaz del objeto agregado con las operaciones para llevar a
cabo los diversos recorridos, incluso si se pudiera anticipar los que se
necesitan.

Proporcionar una interfaz uniforme para recorrer diferentes estructuras agregadas,


es decir, para permitir la iteración polimórfica.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 78/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Scenario
Iterator: declara la interfaz
para recorrer los elementos y
main()
acceder a ellos.

Director

Iterator
Aggregate
first()
next()
createIterator()
isDone()
currentItem()

ConcreteIteratorA ConcreteIteratorB
ConcreteAggregateA ConcreteAggregateB
first() first()
next() next()
createIterator() createIterator()
isDone() isDone()
currentItem() currentItem()

public createIterator() { public createIterator() {


return ne ConcreteIteratorA(this); return ne ConcreteIteratorB(this);
} }

Como mínimo, define los métodos para la navegación, recuperación y validación: first, next, isDone y currentItem.

En agregados ordenados podría añadir previous para posicionar el iterador en el elemento anterior; y

En colecciones ordenadas o indexables aplicando algún criterio, skipTo para posicionar el iterador en un objeto que cumpla
el criterio especificado.

ConcreteIterator: clase derivada de Iterator que implementa la interfaz y mantiene la posición actual en el recorrido
del ConcreteAggregate.

Normalmente las instancias son creadas por ConcreteAggregate. De hecho, debido al alto acoplamiento con dicha clase, la
clase ConcreteIterator es a menudo una clase interna de ConcreteAggregate.

Aggregate: declara la interfaz para crear un objeto Iterator.

ConcreteAggregate: clase derivada de Aggregate que implementa la interfaz para devolver una instancia del
ConcreteIterator apropiado.

Implementación

Variaciones
Un ConcreteIterator puede ser interno o externo dependiendo de quién controla la iteración:

Los iteradores externos proporcionan métodos para que los clientes naveguen por el objeto agregado. Es decir, los
clientes que utilizan un iterador externo deben avanzar en el recorrido demandando explícitamente el siguiente
elemento del agregado al iterador.

Los iteradores internos recorren los elementos llevando a cabo alguna acción solicitada por el cliente. Es decir, el
cliente entrega al iterador interno una operación a realizar, y el iterador aplica la operación a cada elemento del
agregado.

El algoritmo de recorrido puede ser definido en el ConcreteIterator o en el ConcreteAggregate:

Si el algoritmo de recorrido necesita acceder a las variables privadas del agregado, para evitar que el iterador viole
la encapsulación de éste, el propio agregado puede definir el algoritmo y utilizar el iterador para almacenar sólo el
estado del recorrido. Este tipo de iteradores se conocen como cursor, ya que se limitan a señalar la posición actual en el
agregado. Los clientes invocarán sobre el agregado la operación next con el cursor como un argumento y la operación next
cambiará el estado del cursor.

Si el algoritmo de recorrido se define en el iterador, es más fácil usar diferentes algoritmos de iteración sobre el
mismo agregado o reutilizar el mismo algoritmo sobre diferentes agregados.

Puede ser peligroso modificar un agregado mientras un iterador lo está recorriendo. Dependiendo de la manera de
gestionar esta circunstancia, un ConcreteIterator puede ser estático o dinámico:

Los iteradores estáticos crean una imagen del agregado en el momento de ser creados y hacen referencia a esa copia
mientras son utilizados.

Es una solución sencilla pero demasiado costosa como para ser empleada siempre.

Los iteradores dinámicos hacen referencia directamente al agregado subyacente, por lo que deben garantizar que
siempre reflejan su estado.

Un iterador robusto asegura que las inserciones y borrados no interfieren en el recorrido.

Hay muchas maneras de implementar iteradores robustos. La mayoría lo hacen registrando los iteradores con el
agregado. En la inserción o borrado, el agregado o bien ajusta el estado interno de los iteradores que ha producido, o se
mantiene información internamente para asegurar el recorrido adecuado.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 79/117
19/1/2021 Patrones de Diseño

Los iteradores nulos son iteradores degenerados que facilitan el recorrido de agregados con estructura de árbol, ya
que permiten implementar el recorrido sobre una estructura compuesta de un modo uniforme. En cada punto del
recorrido se puede pedir el elemento actual a un iterador para sus hijos. Los elementos Composite devuelven, como norma
general, un iterador concreto. Pero los elementos Leaf devuelven una instancia de iterador nulo, que se caracterizan porque su
operación isDone siempre se evalúa a verdadero. De esta manera es posible utilizar la recursividad para visitar todos los
nodos del árbol.

Consecuencias

Ventajas Desventajas

Permite variaciones en el recorrido de un agregado, es decir, agregados Pueden crear una ilusión de
complejos pueden ser recorridos de múltiples maneras definiendo nuevas subclases estructuras ordenadas. Si un
de Iterator. conjunto no soporta la
ordenación, su iterador podría
Permite tener varios recorridos simultáneos sobre un agregado, ya que cada
proporcionar los elementos en
iterador mantiene su propio estado del recorrido.
una secuencia arbitraria que
Los Iteradores simplifican la interfaz del agregado ya que la interfaz de podría cambiar con el tiempo. Si
recorrido del Iterador obvia la necesidad de una interfaz similar en el agregado. no se tiene en cuenta este hecho,
La posibilidad de definir una interfaz uniforme para recorrer distintos tipos se podría estar presuponiendo
de agregados simplifica mucho el uso de colecciones y permite utilizar el una coherencia en la estructura
polimorfismo cuando se trabaja con ellas. subyacente que podría provocar
problemas en los clientes.

Los iteradores polimórficos


pueden dar lugar a agujeros
de memoria (memory leaks)
en lenguajes como C++, en los
que los clientes son responsables
de liberar la memoria asignada
a un iterador cuando se ha
terminado de usarlo. Esto es
propenso a errores,
especialmente cuando en una
operación hay múltiples puntos
de salida (ej. si se lanza una
excepción, el objeto iterador
podría no liberarse nunca).

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Dependencias algorítmicas Acoplamiento

Mediator
Problema

Motivación

En un encuentro Scenario

deportivo hay dos main()

equipos con sus


correspondientes TeamMember
Match

getRivalTeamld()
participantes
Match(SeverityLevel)
getTeammates()
play()
informTeamMembersAboutAnswer()

(jugadores, capitanes,
entrenadores, …) que Player

tienen que ser capaces requestYellowCard()


requestRedCard()

de
requestPenalti()
requestMassage()
answerYesNoRequest()

[red]responsabilizarse
generateRandom(int, boolean)

de sus funciones
individuales, y
Captain
Coach

performCoinToss() Physiotherapist
requestSubstitution()
también de chooseHeadsOrTails()
chooseGoal()
answerYesNoRequest()
answerSubstitutionRequest()
answerMassageRequest() requestMassage()
answerYesNoRequest()

coordinarse a la hora
provideFinalAnswerAfterConsultingTeamMates()
generateRandom(int, boolean)
informTeamMembersAboutGoal()

de tomar decisiones
sobre el reparto inicial SevereCaptain PermissiveCaptain PermissivePlayer SeverePlayer PermissiveCoach SevereCoach

de campos, o si es generateRandom(int, boolean) generateRandom(int, boolean) generateRandom(int, boolean) generateRandom(int, boolean) generateRandom(int, boolean) generateRandom(int, boolean)

procedente pitar una


tarjeta amarilla o roja o
un penalti, o llevar a
cabo un cambio de
jugadores o solicitar al
fisioterapeuta que preste
sus servicios en el
campo o …, [red]con un
criterio de

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 80/117
19/1/2021 Patrones de Diseño

permisividad* más o
Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
menos severo a la hora
surgen nuevos tipos de participantes que tendrán que intervenir en la coordinación.
de decidir.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Mediator/mediatorWrong)

Acoplamiento Cohesión Granularidad

El acoplamiento de las especializaciones La cohesión de las La granularidad de las especializaciones


derivadas de la clase TeamMember para los especializaciones derivadas de la clase TeamMember para los
distintos tipos de participante del partido derivadas de la distintos tipos de participante del partido
(Player, Captain y Coach) depende de la clase TeamMember (Player, Captain y Coach) depende de la
cantidad de distintos tipos de participantes para los distintos cantidad de métodos requeridos, sean
en el partido (ej. 3). participantes del éstos para cumplir con las responsabilidades
partido (Player, individuales de la clase o para las tareas de
Se calcula como la suma de la cantidad de
Captain, Coach, …) coordinación en la toma de decisiones. Dicha
distintos tipos de participantes en el
no es adecuada cantidad varía para cada tipo de participante
partido (ej. Player, Captain y Coach, 3), con la
puesto que asumen (ej. Player, 4 + 5 = 9; Captain, 2 + 7 = 9; Coach,
simplificación de que todos los participantes
varias 1 + 7 = 8), por lo que se considerará para el
se conocen entre sí.
responsabilidades análisis la media de todos los métodos de
Su resultado es de orden lineal, O(n). dispares o que no las clases que representan a los distintos
les atañen, como la tipos de participante (ej. 8,6).
coordinación y la
Se calcula como la media de los métodos
toma de decisiones
relativos a la responsabilidad de cada
sobre el partido.
clase, sean éstos para cumplir con las
responsabilidades individuales de la clase o
para las tareas de coordinación en la toma de
decisiones; es decir, la suma de los métodos
relativos a la responsabilidad de todas las
clases que representan un tipo de
participante (ej. 7 + 19 = 26) dividido entre el
número de tipos de participante (ej. 3).

Su resultado es de orden lineal, O(n ).

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 81/117
19/1/2021 Patrones de Diseño

En un encuentro Scenario

deportivo, la main()
solución más
habitual es
nombrar un «Director»
Match «Collegue»
árbitro para TeamMember
Match(Referee)
coordinar y tomar play()

decisiones sobre
el partido, con un
criterio de
«Mediator»
«ConcreteCollegueA» Referee

permisividad más Player


performCoinToss()
informTeammembersAboutGoal()
o menos severo, y requestYellowCard()
requestRedCard()
answerYesNoRequest()
answerSubstitutionRequest()
de esta manera requestPenalti()
requestMassage()
answermassageRequest()
informTeamMembrsAboutAnswer()
conseguir que cada generateRandom(int, boolean)

tipo de participante
se centre en sus
«ConcreteCollegueAA»
responsabilidades Captain
«ConcreteColleagueB»
Coach
Physiotherapist
«ConcreteMediatorB»
PermissiveReferee
«ConcreteMediatorA»
SevereReferee
individuales chooseHeadsOrTails()
requestSubstitution() givetMassage() generateRandom(int, boolean) generateRandom(int, boolean)
chooseGoal()
evitando la
necesidad de que
todos los
participantes
tengan que
interactuar entre
ellos para
coordinarse en la
toma de decisiones.

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Mediator/mediatorFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 82/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de las especializaciones La cohesión de las La granularidad de las especializaciones


derivadas de la clase TeamMember para los especializaciones derivadas de la clase TeamMember para los
distintos tipos de participante del partido derivadas de la distintos tipos de participante del partido
(Player, Captain y Coach) depende del tipo de clase TeamMember (Player, Captain y Coach) depende de la
árbitro (ej. Referee, 1). para los distintos cantidad de métodos requeridos para
participantes del cumplir con las responsabilidades
Su resultado es de orden constante, O(1).
partido (Player, individuales de la clase. Dicha cantidad varía
Captain, Coach, …) para cada tipo de participante (ej. Player, 4;
es adecuada puesto Captain, 2; Coach, 1), por lo que se
que cada una considerará para el análisis la media de todos
asume una única los métodos de las clases que representan
responsabilidad, a los distintos tipos de participante (ej.
centrada en sus 2,3).
funciones propias,
Se calcula como la media de los métodos
colaborando con el
relativos a la responsabilidad de cada
servicio de árbitro
clase, es decir, la suma de los métodos
que se ocupa de la
relativos a la responsabilidad de todas las
coordinación y la
clases que representan un tipo de
toma de decisiones
participante (ej. 7) dividido entre el número
sobre el partido
de tipos de participante (ej. 3).

Su resultado es de orden lineal, O(n ).

Intención Aplicabilidad

La intención de este patrón es Simplificar la comunicación entre un conjunto de objetos que se comunican
encapsular en un único objeto con reglas bien definidas, pero de manera compleja. Es decir, objetos cuyas
la manera en la que interdependencias no están estructuradas y son difíciles de entender.
interactúan un conjunto de
Permitir reutilizar objetos evitando que éstos se refieran a otros muchos
objetos. De esta manera se
objetos con los que se comunican.
consigue promover un menor
acoplamiento al evitar a los Permitir que un comportamiento que está distribuido entre varias clases
objetos referirse pueda ser particularizado sin necesidad de muchas subclasificaciones.
explícitamente unos a otros,
así como permitir variar su
interacción de forma
independiente.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 83/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Mediator: declara la interfaz


Scenario
para comunicarse con sus
objetos Colleague.
main()
Permite que los colegas
trabajen con diferentes
subclases de mediador y
Director viceversa.

Collegue Mediator

ConcreteMediatorB ConcreteMediatorA

ConcreteColleagueB ConcreteCollegueA

ConcreteMediator: clase derivada de Mediator que define el comportamiento cooperativo coordinando objetos Colleague.

Colleague: declara la interfaz para comunicarse con el objeto Mediator.

ConcreteColleague: clase derivada de Colleague que define el comportamiento para comunicarse con el objeto Mediator.
Cada Colleague se comunica con su Mediator cada vez que, de no existir éste, se hubiera comunicado con otro Colleague.

Implementación

Variaciones
La clase abstracta Mediator se puede omitir si los colegas siempre trabajan sólo con un mediador.

Existen diversos enfoques para la comunicación Colleague-Mediator:

Se puede implementar el mediador como un observador, utilizando el patrón Observer. Las clases colegas harán las
veces de sujetos, enviando notificaciones al mediador cada vez que cambie su estado; y el mediador responderá
propagando los efectos del cambio a otros colegas.

Se puede definir en el mediador una interfaz de notificación especializada que permite a los colegas ser más
directos en su comunicación, de tal manera que cuando un colega se comunica con el mediador, se pasa a sí mismo como
argumento permitiendo así al mediador identificar al emisor.

Consecuencias

Ventajas Desventajas

Localiza el comportamiento que de otro modo estaría distribuido entre varios La encapsulación de protocolos
objetos. El cambio de este comportamiento requiere únicamente subclases de y la centralización de
mediador, pudiendo ser reutilizadas las clases colegas tal cual, reduciéndose así la comportamiento específico de la
necesidad de subclasificación. aplicación pueden convertir al
objeto mediador en un objeto
Esto permite enfocarse en cómo interactúan los objetos de un sistema más
más complejo que cualquier
allá de su comportamiento individual y simplificar el mantenimiento de la
colega individual y hacer de él
estrategia general de comunicación puesto que ésta es responsabilidad
un monolito difícil de
exclusiva del mediador.
mantener.
Promueve el desacoplamiento entre colegas. Se pueden variar y reutilizar las
clases colega y mediador de forma independiente.

El desacoplamiento entre colegas evita que los distintos objetos no puedan


trabajar sin el soporte de los demás, lo cual podría convertir el sistema en un
monolito difícil de mantener.

Simplifica los protocolos de comunicación entre los objetos, puesto que


sustituye las interacciones muchos-a-muchos entre los objetos (en el peor de los
casos, cada objeto interaccionaría con el resto de los objetos del conjunto), por
interacciones uno-a-muchos entre el mediador y sus colegas. Las relaciones
uno-a-muchos son más fáciles de entender, mantener y extender.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 84/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Poner a funcionar los mecanismos de Reusabilidad Fuerte acoplamiento Acoplamiento


reutilización por
composición,
herencia y/o
parametrización

Memento
Problema

Motivación

Una persona se Scenario

responsabiliza de main()

crear planes que


constan de
distintos public createPlan() {
public undoPlanModification() {
this.planArchive.undo(this.plan.getTitle(),
...
elementos, título, this.plan=new Plan(title, date, participants, details);
this.plan.getParticipants(),
thisplan.getDetails());
this.planActive.regitry(this.plan.getTitle(),
fecha, participantes, this.plan.getPartisipants(),
this.setCoordinatorAndSecretary();
this.plan.getDetails());
detalles,
public redoPlanMotivation() {
} Person
this.planArcive.redo(this.plan.getTitle(),
this.plan.getParticipants(),
coordinador, public modifyPlan() { createPlan()
this.plan.getDetails());
plan.removeDetail(detailToRemove); modifiPlan()
this.setCoordinatorAndSecretary();
secretario…, y de this.plasArchive.registry(this.plan.getTitle(), undoPlanModifiation()
redoPlanModification() }
this.plan.getParticipants(),
reviewAllPlanVersions()
realizar this.plan.getDetails(); setCoordinatorAndSecretary() private setCoordinatorAndSecretary() {
plan.addParticipant(participantToAdd);
int partSize = this.plan.getParticipants().size();
modificaciones this.planArchive.registry(this.plan.getTitle(),
this.plan.setCoordinator((partSize > 0) ?
this.plan.getParticipants(),
this.plan.getParticipants().get(0):"");
sobre los mismos. this.plan.getDetails());
this.plan.setSecretary((partSize > 0) ?
...
this.plan.getParticipants().get(partSize-1) : "");
Para poder }
}

recuperar una
versión anterior
del plan, se PlanArchive

titleLists
responsabiliza partisipantsLists
detailsLists
también de registry(List.String, List.List.String, List.List.String)
undo(List.String, List.List.String, List.List.String)
proporcionar a redo(List.String, List.List.String, List.List.String)
isUndoable()

un archivo isRedoable()
setTitleAndParticipantsAndDetails(List.String, List.List.String, List.List.String)

aquellos
elementos del
plan que pueden
public undo(title, participants, details) {
this.firstPrevious++;
setTitleAndParticipantsAndDetails(title,participants, details); Plan
ser modificados y } title

no se pueden public redo(title,participants, details) {


date
participants
this.firstPrevious--; details
deducir a partir setTitleAndParticipantsAndDetails(title, participants, details) { coordinator
secretary
}
de otros (título, setTitle(String)
private setTitleAndParticipantsAndDetails(title, participants, details) { addPartiipant(String)
participantes y title = this.titleLists.get(firstPrevious); removeParticipant(String)
addDetail(String)
participants.clear();
detalles) para que for (participant : this.participantsLists.get(firstPrevious))
removeDetail(inString)
setCoordinator(String)
participants.add(participant); setSecretary(String)
éste guarde una details.clear(); getTitle()
for (detail : this.detailsLists.get(firstPrevious)) getParticipans()
copia de los mismos details.add(detail);
getDetails()

}
y así poder
consultarlos Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
posteriormente. surgen nuevos elementos del plan que pueden ser modificados y no se pueden deducir a partir
de otros.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Memento/mementoWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 85/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 2) La cohesión de la La granularidad de los métodos de la clase


depende del tipo del plan (ej. Plan, 1) y del clase Person no es Person (ej. 3) depende de los elementos del
tipo del archivo en el que se almacena (ej. adecuada puesto plan que pueden ser modificados y no se
PlanArchive, 1). que asume varias pueden deducir a partir de otros.
responsabilidades
Su resultado es de orden constante, O(1). Se calcula como la suma de los elementos
dispares o que no
del plan que pueden ser modificados y no
le atañen, como
se pueden deducir a partir de otros (ej.
proporcionar al
título, participantes y detalles, 3).
archivo aquellos
elementos del plan Su resultado es de orden lineal, O(n).
que pueden ser
modificados y no se
pueden deducir a
partir de otros,
violando la
encapsulación.

Intención

Si la
responsabilidad
de persona
incluye
únicamente la
creación y
modificación de
planes, y otros,
planes, se
responsabilizan
por separado de
proporcionar a
un archivo una
copia de aquellos
elementos del
plan que pueden
ser modificados y
no se pueden
deducir a partir
de otros (título,
participantes y
detalles), ninguna
clase será compleja
y se evitará la
tendencia a crecer,
y se preservará la
encapsulación del
plan.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 86/117
19/1/2021 Patrones de Diseño

Scenario

main()

public createPlan() {
...
this.plan=new Plan(title, date, participants, details);
«Director»
this.planActive.regitry(); Person public undoPlanModification() {
} this.planArchive.undo(this.plan);
createPlan()
public modifyPlan(Plan plan) { modifYPlan() public redoPlanMotivation() {
plan.removeDetail(detailToRemove); undoPlanModifiation() this.planArcive.redo(this.plan);
this.planArchive.registry(); redoPlanModification() }
reviewAllPlanVersions()
plan.addParticipant(participantToAdd);
this.planArchive.registry(this.plan.getTitle();
}

«Caretaker»
PlanArchive
planVersions
registry()
undo()
redo()
isUndoable()
isRedoable()

«Originator»
Plan
title
public undo() {
date this.firstPrevious++;
participants this.plan.setPlanVersion(
details this.planVersions.get(this.firrstPrevious));
coordinator }
secretary
public redo() {
createPlanVersion() this.firstPrevious--;
setPlanVersion(PlanVersion) this.plan.setPlanVersion(
setTitle(String)
this.planVersions.get(this.firrstPrevious));
addParticipant(String)
removeParticipant(String) }
addDetail(String)
removeDetail(String)

public createPlanVersion() {
return new PlanVersion(this.title,
this.participants,
this.details)
«Memento»
}
PlanVersion

public setPlanVersion(planVersion) { title


participants
this.title = planVersion.getTitle();
details
this.participants = planVersion.getParticipants();
details = planVersion.getDetails(); getTitle()
this.coordinator = (this.participans.size() > 0) ? getParticipans()
getDetails()
this.participants.get(0) : "";
this.secretary = (this.participants.size() > 0) ?
this.participants.get(this.participants.size() -1 : "";
}

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Memento/mementoFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 2) La cohesión de la La granularidad de los métodos de la clase


depende del tipo del plan (ej. Plan, 1) y del clase Person es Person (ej. 1) depende del plan.
tipo del archivo en el que se almacena (ej. adecuada puesto
Su resultado es de orden constante, O(1).
PlanArchive, 1). que asume una
única
Su resultado es de orden constante, O(1).
responsabilidad,
centrada en la
gestión de planes,
colaborando con el
servicio del plan
para proporcionar
al archivo aquellos
elementos del plan
que pueden ser
modificados y no se
pueden deducir a
partir de otros.
preservando la
encapsulación.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 87/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es, Aplicable cuando se cumplen las dos siguientes condiciones:
sin violar la encapsulación,
Se necesita guardar una instantánea del estado interno de un objeto (o de
capturar y externalizar el
parte de éste) para poder restaurar el objeto a dicho estado posteriormente.
estado interno de un objeto de
Tiene gran utilidad cuando se implementan mecanismos de deshacer que
tal forma que el objeto puede
permiten a los usuarios anular operaciones provisionales y/o recuperarse de
ser restaurado a este estado
errores.
después.
Se quiere evitar utilizar una interfaz directa para obtener el estado del
objeto que pudiera violar el principio de encapsulación por exponer detalles
de implementación internos.

Solución

Estructura General Participantes

Originator: clase que crea un


Scenario
objeto Memento, el cual contiene
una instantánea de su estado
main()
interno actual, y que puede
utilizar posteriormente dicho
Memento para volver a ese
estado.
Director

Caretaker

getMemento()
add(Memento)

public createMemento() {
return new Memento(state); Originator
}
state
public setMemento(memento) { createMemento()
state = memento.getState(); setMemento(Memento)
}

Memento

state
getState()
setState()

Memento: clase que almacena el estado interno del objeto Originator. Tiene dos interfaces:

Una interfaz amplia, que permite al Originator acceder a todos los datos necesarios para volver a su estado anterior.

Una interfaz reducida, que sólo permite pasar el objeto Memento a otros objetos, protegiendo así el Memento frente a
accesos que no provengan del Originator. Solo el Originator puede almacenar y recuperar información del Memento – el
Memento es “opaco” a otros objetos.

Caretaker: clase responsable de guardar en lugar seguro los objetos Memento, así como de borrar los Memento que
custodia. Nunca examina sus contenidos ni opera sobre ellos, es decir, sólo conoce la interfaz reducida del Memento.

Implementación

Variaciones
La implementación del patrón Memento es muy dependiente del lenguaje de implementación:

Lo ideal sería que el lenguaje de implementación permitiese dos niveles de protección estática. C++ lo permite haciendo
que Originator sea una clase amiga de Memento, y manteniendo privada la interfaz amplia del Memento y pública la
interfaz reducida.

En otros lenguajes como Java, debido a que el Memento debería ser accesible únicamente desde el Originator, se
puede hacer que el Memento sea una clase interna pública del Originator, declarando todos los métodos privados
para que sólo estén disponibles para el objeto Memento y su clase contenedora Originator, ofreciendo así la encapsulación
apropiada. Dado que el objeto Memento debe ser independiente de una instancia específica de un Originator, la clase
Memento será una clase interna estática.

La cantidad de información que almacena el objeto Memento variará en función de lo que necesite el objeto
Originator para ser capaz de volver a un estado previo. En caso de que los Memento se creen y se devuelvan en una
secuencia predecible, es decir, en un orden concreto, el Memento puede guardar únicamente el cambio con respecto al estado

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 88/117
19/1/2021 Patrones de Diseño

interno anterior del Originator.

Consecuencias

Ventajas Desventajas

El Memento evita exponer información que sólo debería ser manejada por el El uso del patrón Memento
Originator, pero que sin embargo debe ser guardada fuera de éste. El patrón podría suponer un coste
preserva la encapsulación, lo cual permite: considerable si el Originator
debe copiar grandes
Simplificar el Originator, ya que se evita que éste tenga que responsabilizarse
cantidades de información
de registrar y almacenar todos los estados distintos solicitados por los clientes
para guardarlas en el Memento o
para preservar la encapsulación, ocupándose únicamente de crear los objetos
si los clientes crean y devuelven
Memento y de saber utilizarlos cuando los clientes se lo soliciten.
Mementos a su Originator con
Simplificar los clientes, ya que estos no necesitan saber nada sobre el mucha frecuencia. A menos
funcionamiento interno del Originator, que podría ser potencialmente complejo, que encapsular y restablecer
excepto cómo obtener un Memento y cómo utilizarlo, y evita que los clientes el estado sea poco costoso, el
tengan que notificar a los objetos Originator cuando han acabado. patrón podría no ser
No comprometer la fiabilidad y extensibilidad de la aplicación exponiendo apropiado.
interioridades de los objetos innecesariamente. Una de las principales
clases afectadas por este
coste es Caretaker ya que,
aunque desconoce cuánto
estado hay en un Memento,
es la responsable de
gestionar el ciclo de vida de
estos objetos tras su
creación.

En algunos lenguajes puede


ser difícil garantizar que sólo
el Originator acceda al estado
del Memento.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Especificar interfaces de objetos Abstracción Dependencias de las representaciones o Acoplamiento


implementaciones de objetos

Observer
Problema

Motivación

Una persona puede Scenario

tener distintos
main()

tipos de Fate

problemas en la provideLifeEventsForMan(Man)
provideLifeEventsForWoman(Woman)

vida, pérdida de un
ser querido o Person

padecimiento de
inTrouble
isInTrouble()
setInTrouble(TroubleReason)

una enfermedad o
getTroubleReason()
loseALovedOne()
haveAFlue()
public notifyKnownPeople() {
wasteAllSavings()

falta de liquidez o
if (this.isNotOrphan()) beBom()
mother.update(); becomOrphan() Partner Mother Boss
if (this.isInRelationship()) startRelationship()
update

…, ante los que tiene


partner.update(); endRelationship()
setPerson(Person) setPerson(Person)
if (this.isEmployed()) startJob()
update() update() setPerson(Person)
endJob()
boss.update(); isNotOrphan()

que requerir
} isInRelationship()
isEmployed()
attach(Mother)
detach(Mother)

ayuda a una serie arttach(Partner)


detach(Partner)
attach(Boss)

de distintas
detach(Boss)
notifyKnownPeople()

personas de su
entorno, madre o
public update() {
swich (this.person.getTroubleReason()) {
public update() { case SAD:

pareja o jefe o…,


Woman if(this.person.getTroubleReason() == ILL) // Mother conforting you by phone public update() {
Man // Partner taking you to doctor case ILL: if(this.person.getTroubleReason() == ILL)
getPregmant() else if (this.person.get(TroubleReason() == SAD) // Mother visiting you and bringing food // Boss giving you a sick leave

para sobrellevar
havePreeclampsia() // Partner giving you a hug case WITHOUT_MONEY: }
} // Mother lending you money
}

este valle de
}

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


lágrimas.
surgen nuevos tipos de personas en el entorno a los que solicitar ayuda.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Observer/observerWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 89/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 3) La cohesión de la La granularidad de la clase Person (ej. 22)
depende del número de tipos de personas clase Person no es depende de la cantidad de métodos
de su entorno encargados de prestar adecuada puesto requeridos.
ayuda. que asume varias
Se calcula como la suma de los métodos
responsabilidades
Se calcula como la suma del número de relativos a la responsabilidad de la clase
dispares o que no
tipos de personas de su entorno para gestionar los distintos tipos de
le atañen, como la
encargados de prestar ayuda (ej. Mother, problemas en la vida (ej. isInTrouble,
gestión de los
Partner y Boss, 3). setInTrouble, getTroubleReason,
distintos tipos
loseALovedOne, haveAFlue, wasteAllSavings,
Su resultado es de orden lineal, O(n). personas que le
…, 12) más el producto del número de tipos
prestan ayuda
de personas de su entorno (ej. Mother,
según las
Partner y Boss, 3) por los métodos relativos
circunstancias.
para gestionar la existencia de cada tipo
de persona (ej. attach, detach e is, 3), más el
método para realizar la notificación (ej.
notifyKnowPeople, 1).

Su resultado es de orden lineal, O(n).

Intención

Una persona puede Scenario

tener distintos tipos


main()

de problemas en la «Subject»

vida, pérdida de un ser


Person
inTrouble

querido o padecimiento
isInTrouble()
setInTrouble(TroubleReason)
getTroubleReason()
public notifyKnownPeople() { loseALovedOne() «Director» «Observer»

de una enfermedad o haveAFlue() Fate KnownPeople


for each knownPeople in this knownPeople
wasteAllSavings()
people.update();
beBom() provideLifeEventsForMan(Man) setPerson(Person)
}

falta de liquidez o …,
becomOrphan() provideLifeEventsForWoman(Woman) update()
startRelationship()
endRelationship()
startJob()

ante los que notifica endJob()


attach(KnownPeople)
detach(KnownPeople)

que requiere ayuda a


notifyKnownPeople()

una serie de «ConcreteSubjectB» «ConcreteObserverC» «ConcreteObserverA» «ConcreteObserverB»

personas de su
Woman «ConcreteSubjectA» Boss Mother Partner
Man
update
getPregmant() setPerson(Person) setPerson(Person)

entorno que le
havePreeclampsia() setPerson(Person) update() update()

atienden, madre o public update() {

pareja o jefe o…, para


swich (this.person.getTroubleReason()) {
case SAD: public update() {
public update() { // Mother conforting you by phone if(this.person.getTroubleReason() == ILL)

sobrellevar este valle


if(this.person.getTroubleReason() == ILL) case ILL: // Partner taking you to doctor
// Boss giving you a sick leave // Mother visiting you and bringing food else if (this.person.get(TroubleReason() == SAD)
} case WITHOUT_MONEY: // Partner giving you a hug

de lágrimas. }
// Mother lending you money }

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Observer/observerFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 90/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 1) La cohesión de la La granularidad de la clase Person (ej. 15)
depende de un tipo de persona conocida clase Person es depende de la cantidad de métodos
(ej. KnownPeople, 1). adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
para gestionar los distintos tipos de
centrada en la
problemas en la vida (ej. isInTrouble,
gestión de su vida,
setInTrouble, getTroubleReason,
notificando que
loseALovedOne, haveAFlue, wasteAllSavings,
requiere ayuda a la
…, 12) más los métodos relativos para
red de seguridad de
gestionar la existencia de un tipo de
personas de su
persona conocida (ej. attach y detach, 2),
entorno.
más el método para realizar la
notificación (ej. notifyKnowPeople, 1).

Su resultado es de orden lineal, O(n).

Intención Aplicabilidad

La intención de este patrón es Abstracciones que tienen dos aspectos, uno de los cuales depende del otro. La
definir una dependencia uno- encapsulación de estos aspectos en objetos separados permite modificarlos y
a-muchos entre objetos de tal reutilizarlos de manera independiente.
forma que cuando un objeto
Un cambio sobre un objeto requiere cambiar otros y no se conoce cuántos
cambia su estado, todos los
objetos necesitan ser cambiados.
objetos dependientes son
notificados y actualizados Un objeto debería ser capaz de notificar a otros objetos sin hacer asunciones
automáticamente. sobre quiénes son estos objetos. En otras palabras, no se quiere estos objetos
altamente acoplados, para permitir una mayor reusabilidad.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 91/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Scenario Subject: declara la interfaz para


main() registrar y desregistrar objetos
Observer, así como para realizar
Director la notificación a los mismos
cuando se produce en él algún
cambio relevante.
public notify() { Subject
for each observer in observer
Observer
El sujeto observado puede
observer.update(); attach(Observer)
} detach(Observer)
notify()
update()
tener cualquier número de
observadores dependientes.

ConcreteObserverA ConcreteObserverB
Todos los observadores que se
observerStateA observerStateB hayan suscrito previamente
update() update()
son notificados si el
observado sufre un cambio
ConcreteSubjectB ConcreteSubjectA
public update() { public update() { de estado.
subjectStateA subjectStateA observerStateA = subject.getStateA(); observerStateB = subject.getStateB();
getStateA() getStateA() } }
setStateA() setStateA()

Se envían notificaciones sin


tener conocimiento de
quienes son sus observadores.

ConcreteSubject: clase derivada de Subject que implementa la interfaz:

Almacena el estado de interés para los objetos ConcreteObserver.

Envía una notificación a sus observadores cuando cambia su estado.

Necesita mantener una colección de Observer para efectuar las notificaciones.

Observer: declara la interfaz para actualizar los objetos que deben ser notificados ante cambios en un Subject.

En respuesta a la notificación recibida, cada observador consultará al sujeto observado para sincronizar su estado con el
estado de éste.

ConcreteObserver: clase derivada de Observer que implementa la interfaz:

Mantiene una referencia a un ConcreteSubject.

Guarda un estado que debería ser consistente con el del sujeto.

Implementa los métodos para responder a las notificaciones recibidas, garantizando la correcta actualización de su
estado, es decir, su actualización de manera consistente con el estado del sujeto al que observa.

Implementación

Variaciones
Hay diversas opciones para implementar la correspondencia entre los sujetos observados y sus observadores:

La forma más simple para que un sujeto realice el seguimiento de los observadores a los que debería notificar sería
almacenar explícitamente las referencias a los observadores. Sin embargo, esto puede ser muy costoso desde el punto
de vista del espacio de almacenamiento cuando hay muchos sujetos observados y pocos observadores.

Otra alternativa es utilizar un array asociativo para búsquedas (por ejemplo, una tabla hash) que mantiene la
correspondencia entre sujetos observados y sus observadores. Este enfoque consigue reducir el coste de almacenamiento a
costa de incrementar el tiempo de acceso, consiguiéndose así un compromiso espacio/tiempo.

En caso de que un observador dependa de más de un sujeto observado, es necesario extender el interfaz de actualización
para permitir al observador conocer qué sujeto observado está enviando la notificación. El sujeto observado puede
simplemente enviarse a sí mismo como parámetro de la operación de actualización permitiendo al observador conocer a qué
sujeto consultar.

Existen dos alternativas para disparar las actualizaciones que mantienen consistentes los estados del sujeto y sus
observadores utilizando el mecanismo de notificación:

Las operaciones que modifican el estado del sujeto se responsabilizan de enviar la notificación a los observadores
después de cambiar el estado del sujeto.

La ventaja de este enfoque es que los clientes no tienen que estar pendientes de indicar al sujeto que envíe las
notificaciones.

La desventaja es que varios cambios consecutivos en el sujeto causarán notificaciones consecutivas a los observadores,
que dispararán sus correspondientes actualizaciones, lo cual puede resultar ineficiente.

Los clientes se responsabilizan de enviar las notificaciones en el momento adecuado.

La ventaja es que el cliente puede esperar para hacer el envío de éstas hasta que se hayan realizado una serie de
cambios de estado en el sujeto observado, evitando de este modo actualizaciones intermedias innecesarias por parte de
los observadores.

La desventaja es que los clientes tienen una responsabilidad añadida para activar la actualización, lo cual incrementa la
probabilidad de errores, ya que los clientes podrían olvidarse, en un momento dado, de hacer el envío.

En caso de que un sujeto observado sea eliminado, no deben producirse referencias “colgadas” de sus observadores.
Una forma de evitar esto es que el sujeto observado notifique a sus observadores cuando se elimina, de modo que éstos
puedan reinicializar la referencia a él. En general, la alternativa de borrar los observadores no es una opción, ya que otros

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 92/117
19/1/2021 Patrones de Diseño

objetos pueden hacer referencia a ellos, o ellos mismos pueden estar observando a otros sujetos.

Es importante asegurar que el estado del sujeto observado es consistente consigo mismo antes de enviar las
notificaciones a los observadores, ya que éstos consultarán al sujeto por su estado actual durante el proceso de actualizar su
propio estado.

Esta regla de auto-consistencia se puede violar involuntariamente cuando subclases del sujeto observado llaman a métodos
heredados. Para evitarlo, se pueden utilizar métodos plantilla cuya última operación sea el envío de notificaciones, y en la
que las subclases únicamente redefinirán las operaciones previas al envío según sus responsabilidades.

Habitualmente, el sujeto observado transmite información adicional acerca del cambio experimentado como un
argumento de la actualización. La cantidad de información puede variar ampliamente. Existen diversos enfoques para esta
transmisión entre Subject-Observer:

En un extremo, se encuentra el modelo de inserción (push), en el cual el sujeto observado envía información detallada a
los observadores sobre el cambio, lo quieran o no. El modelo de inserción asume que los sujetos saben algo acerca de las
necesidades de sus observadores.

En el otro extremo, se encuentra el modelo de extracción (pull), en el cual el sujeto observado envía únicamente la
notificación mínima, y los observadores consultarán por los detalles de forma explícita posteriormente. El modelo de
extracción hace hincapié en la ignorancia del sujeto sobre sus observadores.

La complejidad de la relación de dependencia entre los sujetos y los observadores puede requerir la utilización de un
objeto que encapsule la semántica de las actualizaciones, denominado ChangeManager. Su objetivo es reducir al
mínimo el trabajo necesario para hacer que los observadores reflejen un cambio en sus observados. Por ejemplo, si una
operación involucra cambios en varios sujetos observados interdependientes, puede que tenga que asegurarse de que sus
observadores son notificados después de que todos los sujetos se han modificado para evitar la notificación a los observadores
más de una vez. ChangeManager tiene tres responsabilidades:

Relacionar un sujeto observado y sus observadores, proporcionando una interfaz para mantener esta relación. Se
elimina así la necesidad de que los sujetos observados mantengan las referencias a sus observadores y viceversa.

Definir una estrategia de actualización en particular.

Actualizar todos los observadores dependientes a petición de un sujeto.

Se puede mejorar la eficiencia en la actualización mediante la ampliación de interfaz de registro del sujeto observado
permitiendo que los observadores se registren sólo para eventos específicos de su interés en lugar de hacer un registro
genérico que incluiría cualquier evento. Cuando tal evento se produce, el sujeto observado informa sólo a aquellos
observadores que hayan registrado interés en ese evento. Una forma de apoyar esto es utilizar la noción de aspectos en los
objetos sujeto.

Consecuencias

Ventajas Desventajas

Permite variar independientemente observados y observadores. Se pueden Se pueden producir


reutilizar los sujetos observados sin reutilizar sus observadores y viceversa. Esto actualizaciones inesperadas,
posibilita añadir observadores sin modificar los sujetos observados u otros debidas a que, como los
observadores. observadores no tienen
conocimiento de la presencia de
Todo sujeto observado conoce que tiene una lista de observadores, conforme a
otros, no pueden ver el coste
la sencilla interfaz de la clase abstracta Observer, pero el sujeto no conoce la
final de modificar el sujeto
clase concreta de ninguno de sus observadores.
observado.
El acoplamiento entre sujetos observados y observadores es abstracto y mínimo,
Una operación
pudiendo éstos pertenecer incluso a capas diferentes de abstracción del sistema.
aparentemente inocua sobre
Si se agrupasen el sujeto y el observador en un único objeto, el objeto resultante el sujeto puede provocar una
debería abarcar dos capas (violando la arquitectura de capas) o ser forzado a cascada de cambios en los
residir en una capa u otra (lo que podría comprometer las abstracciones de las observadores y sus objetos
capas). dependientes.
La notificación que envía el observado no necesita especificar sus receptores. Por otra parte, si existen
La notificación es multidifundida (broadcast) automáticamente a todos los objetos criterios de dependencia que
que estén suscritos. El observado no se preocupa de cuántos objetos interesados no estén bien definidos o
existen; su responsabilidad solo es notificar a sus observadores. Esto da la libertad mantenidos, podrían dar
de añadir y borrar observadores en cualquier momento. El observador ya verá si lugar a cambios espurios, que
maneja o ignora la notificación pueden ser difíciles de
localizar. Este problema se ve
agravado por la utilización de
un protocolo simple de
actualización que no
proporcione ningún detalle
sobre lo que ha cambiado
en el sujeto observado. Sin
un protocolo adicional para
ayudar a los observadores a
descubrir estos cambios, la
tarea de deducirlos puede no
ser en absoluto trivial.

Problemas de Diseño y Rediseño

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 93/117
19/1/2021 Patrones de Diseño

Problemas de Diseño Problemas de Rediseño

Especificar la Implementación de Implementación Fuerte acoplamiento Acoplamiento


Objetos

Relacionar Estructuras del Tiempo de Acoplamiento Añadir funcionalidad mediante herencia Principio
Compilación y de Ejecución Abierto/Cerrado

State
Problema

Motivación

Una persona
Scenario
realiza diversas
actividades a lo
main()
largo del día,
comer o bailar o
trabajar o …, pero
dependiendo de
public eat() {
su estado de
if (this.mood == AvailableMood.HAPPY) {
ánimo, feliz o triste this.eatHappy();
o …, las realizará } else if (this.mood == AvailableMood.SAD) {
con distintos this.eatSad();
algoritmos. }
}
Person
public dance() {
mood if(this.mood == AvailableMood.HAPPY) {
eat() this.danceHappy();
dance() } else if (this.nood == AvailableMood.SAD) {
work() this.danceSad();
eatHappy() tis.mood = AvailableMood.HAPPY;
eatSad()
}
danceHappy()
danceSad() }
workHappy()
workSad() public work() {
if (this.mood == AvailableMood.HAPPY) {
tis.workHappy();
this.mood == AvaailableMood.SAD;
} else if (this.mood == AvailableMood.SAD) {
this.workSad();
}
}

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que surgen


nuevos estados de ánimo.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/State/stateWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 94/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 0) es La cohesión de la La granularidad de la clase Person (ej. 9)


nulo. clase Person no es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume varias
Se calcula como la suma de los métodos
responsabilidades
relativos a la responsabilidad de la clase
dispares o que no
(ej. eat, dance y work, 3) más el producto del
le atañen, como la
número de responsabilidades de la clase
definición de
por el número de estados de ánimo (ej. feliz
distintos algoritmos
y triste, 2, por eat, dance y work, 3).
para cada
actividad. Su resultado es de orden cuadrático, O(n2).

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 95/117
19/1/2021 Patrones de Diseño

La
Scenario
responsabilidad
de la persona
main()
incluye la
delegación de la
realización de la
actividad en
public eat() {
diferentes estados
this.mood.eat();
de ánimo, que se }
responsabilizan
«Context»
por separado del Person public dance() {
algoritmo a this.mood.dance();
mood this.mood = new Happy();
seguir para
eat() }
realizar cada dance()
actividad work() public work() {
dependiendo del this.mood.work();
this.mood = new Sad();
estado de ánimo.
}
De esta manera,
ninguna clase será
compleja y se
evitará la tendencia
a crecer. «State»
Mood

eat()
dance()
work()

«ConcreteStateA» «ConcreteStateB»
Happy Sad

eat() eat()
dance() dance()
work() work()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/State/stateFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 1) La cohesión de la La granularidad de la clase Person (ej. 3)


depende del tipo del estado de ánimo (ej. clase Person es depende de la cantidad de métodos
Mood, 1). adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. eat, dance y work, 3).
centrada en la
delegación, Su resultado es de orden lineal, O(n).
colaborando con el
servicio del estado
de ánimo y sus
algoritmos
específicos.

Intención Aplicabilidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 96/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es El comportamiento de un objeto depende de su estado, y debe cambiar en


permitir a un objeto alterar su tiempo de ejecución dependiendo de ese estado.
comportamiento cuando su
Para definir los estados internos se usan valores de datos (a menudo una o más
estado interno cambia
constantes enumeradas) y las operaciones consultan dichos estados
pareciendo que el objeto
explícitamente, dando lugar a largas sentencias condicionales con múltiples
cambia su clase.
ramas que dependen del estado del objeto. Muchas veces son varias las
operaciones que contienen esta misma estructura condicional, por lo que cuando se
necesita añadir un nuevo estado podría necesitarse cambiar varias operaciones,
complicando el mantenimiento.

El patrón State pone cada rama de la condición en una clase aparte, lo cual
permite tratar al estado del objeto como un objeto de pleno derecho que puede
variar de manera independiente de otros objetos.

Solución

Estructura General Participantes

Context: declara una interfaz de


Scenario
interés para los clientes y
mantiene una instancia de una
main()
subclase ConcreteState que
define su estado actual.

Delega todas las llamadas a


los métodos específicos del
Context public request() {
state.handle(); estado actual.
request() }

State

handle()

ConcreteStateA ConcreteStateB

handle() handle()

State: declara una interfaz para encapsular el comportamiento asociado con un determinado estado del objeto Context.

ConcreteState: clase derivada de State que implementa un comportamiento específico asociado con un estado de Context.

Implementación

Variaciones
El patrón State no especifica qué participante define los criterios para las transiciones entre estados. Se puede optar
entre diversas opciones:

Si estos criterios son fijos, pueden implementarse enteramente en Context.

No obstante, es generalmente más flexible y conveniente que sean las propias subclases ConcreteState quienes
especifiquen su estado sucesor y cuándo llevar a cabo la transición. Esto requiere añadir una interfaz a Context que
permita a los objetos State asignar explícitamente el estado actual del contexto.

Descentralizar de esta forma la lógica de la transición facilita modificar o extender dicha lógica definiendo nuevas
subclases de State.

Una desventaja de la descentralización es que una subclase de State conocerá al menos a otra, lo que introduce
dependencias de implementación entre subclases.

También existe otra alternativa basada en tablas de correspondencia. Para cada estado, una tabla hace corresponder
cada posible entrada con un estado sucesor. Este enfoque convierte código condicional (y funciones virtuales, en el caso
del patrón State) en una tabla de búsqueda. La principal ventaja de las tablas es su regularidad: se pueden cambiar los
criterios de transición modificando datos en vez del código del programa. No obstante, este enfoque presenta algunos
inconvenientes:

Es menos eficiente que una llamada a una función.

Los criterios de transición son menos explícitos.

Es más difícil realizar algún tipo de procesamiento arbitrario con cada transición. Para ello es necesario
complementar esta técnica con algún otro mecanismo.

Existen dos alternativas para la creación de los objetos State:

Instanciación diferida, es decir, creación de los objetos cuando se necesitan (y destrucción cuando dejan de ser
necesarios).

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 97/117
19/1/2021 Patrones de Diseño

Este enfoque es preferible cuando no se conocen los estados en tiempo de ejecución y los contextos cambian de
estado con poca frecuencia. Se evita así crear objetos que no se usarán nunca, lo que puede ser importante si los
objetos State guardan una gran cantidad de información.

Creación inicial (sin destrucción).

Este enfoque es más adecuado cuando los cambios tienen lugar rápidamente, en cuyo caso interesa evitar
destruir los objetos State, ya que pueden volver a necesitarse de nuevo en breve. Los costes de creación se pagan al
principio y no existen costes de destrucción. No obstante, esta alternativa tiene el inconveniente de que el objeto Context
debe guardar referencias a todos los estados en los que pueda entrar.

Consecuencias

Ventajas Desventajas

Sitúa en un objeto todo el comportamiento asociado con un determinado El patrón aumenta el número
estado. Como todo el código dependiente del estado reside en una subclase de State, de objetos de una aplicación.
pueden añadirse fácilmente nuevos estados y transiciones definiendo nuevas
A veces se puede reducir este
subclases.
coste si los objetos State no
Esto incrementa el número de clases y es menos compacto que una única tienen variables, es decir, si el
clase, pero se evita que la lógica que determina las transiciones entre estados estado que representan está
resida en grandes sentencias if o switch monolíticas, siendo en su lugar repartida totalmente representado por
entre las subclases de State. su tipo, pudiendo así varios
contextos compartir un
Al encapsular cada transición y acción en una clase, estamos elevando la idea de
mismo objeto State. Cuando
un estado de ejecución a objetos de estado en toda regla. Esto impone una
se comparten los estados de
estructura al código y hace que su intención sea más clara.
este modo, son en esencia
Introducir objetos separados para los diferentes estados hace que las transiciones objetos FlyWeight que no
sean más explícitas. Además, los objetos State pueden proteger a Context frente a tienen estado intrínseco,
estados internos inconsistentes, ya que las transiciones entre estados son atómicas sino solo comportamiento.
para él puesto que tienen lugar cambiando una única variable (la variable de tipo
State del objeto Context).

Si en lugar de utilizar objetos State, un objeto define su estado actual únicamente


en términos de valores de datos internos, sus transiciones entre estados carecen
de una representación explícita; solo aparecen como asignaciones a
determinadas variables.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Encontrar objetos apropiados Cohesión

Especificar la Implementación de Objetos Implementación

Poner a funcionar los mecanismos de Reusabilidad por


reutilización composición,
herencia y/o
parametrización

Strategy
Problema

Motivación

Una persona Scenario

realiza diversas main()

actividades a lo
largo de su vida,
public flirt() { public flirt() {
flirtear o hacer // Trying to flirt
Person
// Trying to make frienship
if (this.approach == Approach.SHARED_FRIEND) { if (this.approach == Approach.SHARED_FRIEND) {
amistades o …, this.approachWithSharedFriendApproach();
} else if (this.approach == Approach.SHARED_HOBBY) {
setApproach()
this.approachWithSharedFriendApproach();
} else if (this.approach == Approach.SHARED_HOBBY) {
flirt()
pero tras realizar this.approachWithSharedHobbyApproach();
} else if (this.approach == Approach.STRAIGHTFORWARD)
makeFriendship()
apporoachWithSharedFriendApproach()
this.approachWithSharedHobbyApproach();
} else if (this.approach == Approach.STRAIGHTFORWARD)

un análisis del this.approachWitStraightForwardApproach(); this.approachWithStraightForwardApproach();


apporoachWithSharedHobbyApproach()
// Inviting to dinner apporoachWithSharedForwardApproach() // inviting to match
} }
contexto, las
realizará con
distintas
estrategias que
implementarán el Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
algoritmo surgen nuevas estrategias.
correspondiente.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Strategy/strategyWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 98/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 0) es La cohesión de la La granularidad de la clase Person (ej. 6)


nulo. clase Person no es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume varias
Se calcula como la suma de los métodos
responsabilidades
relativos a la responsabilidad de la clase
dispares o que no
(ej. flirt y makeFriendship, 2) más el número
le atañen, como la
de estrategias de aproximación (ej. amigo
definición de
común, hobby común e invitación directa, 3)
distintos algoritmos
más el método para analizar el contexto y
para cada
establecer la estrategia (ej. setApproach, 1).
actividad.
Su resultado es de orden lineal, O(n).

Intención

Si la
Scenario
responsabilidad
de persona main()

incluye
únicamente la
delegación de la
«Director»
realización de la SentimentalCounselor
actividad y otros,
teachSharedFriendApproach(Person)
consejero teachSharedHobbyApproach(Person)
teachSharedForwardApproach(Person)
sentimental y
estrategias de
aproximación, se
responsabilizan
public flirt() { «Context»
por separado del // Trying to flirt Person
análisis del this.approach.approach();
set(Approach)
// Inviting to dinner
contexto y del }
flirt()
makeFriendship()
algoritmo a
seguir para
realizar cada
actividad, ninguna public makeFrienship() {
«Strategy»
clase será compleja // Trying to make frienship
Approach
this.approach.approach();
y se evitará la // inviting to match
approach()
tendencia a crecer. }

«ConcreteStrategyB» «ConcreteStrategyA» «ConcreteStrategyC»


SharedFriendApproach SharedHobbyApproach StraightForwardApproach

approach() approach() approach()

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Strategy/strategyFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 99/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Person (ej. 1) La cohesión de la La granularidad de la clase Person (ej. 3)


depende del tipo de la estrategia de clase Person es depende de la cantidad de métodos
aproximación (ej. Approach, 1). adecuada puesto requeridos.
que asume una
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. flirt y makeFriendship, 2) más el método
centrada en la
para recibir la estrategia a aplicar (ej. set,
delegación,
1).
colaborando con el
servicio de la Su resultado es de orden lineal, O(n).
estrategia de
aproximación y sus
algoritmos
específicos.

Intención Aplicabilidad

La intención de este patrón es Muchas clases relacionadas difieren en su comportamiento. Las estrategias
definir una familia de permiten configurar una clase con un determinado comportamiento de entre
algoritmos, encapsulando muchos posibles en tiempo de ejecución.
cada uno y haciéndolos
Se necesitan distintas variantes de un algoritmo, por ejemplo, con distintas
intercambiables, permitiendo
soluciones de compromiso entre tiempo y espacio. Pueden usarse estrategias
al algoritmo variar de manera
cuando estas variantes se implementan como una jerarquía de clases de algoritmos.
independiente del cliente que
lo utilice. Un algoritmo usa datos que los clientes no deberían conocer. El patrón Strategy
permite evitar exponer estructuras de datos complejas y dependientes del
algoritmo.

Una clase define muchos comportamientos, y éstos se representan como


múltiples sentencias condicionales en sus operaciones.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 100/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Strategy: declara una interfaz


Scenario
común a todos los algoritmos
permitidos. Context utiliza esta
main()
interfaz para llamar al algoritmo
definido por una
ConcreteStrategy.

Director

Context

contextInterface()

Strategy

AlgorithmInterface()

ConcreteStrategyB ConcreteStrategyA

AlgorithmInterface() AlgorithmInterface()

ConcreteStrategy: clase derivada de Strategy que implementa un algoritmo específico.

Context: clase que utiliza las diferentes estrategias para una determinada tarea. Se configura con un objeto
ConcreteStrategy y mantiene una referencia al objeto Strategy que está utilizando en cada momento.

Puede definir una interfaz que permita a una ConcreteStrategy acceder a sus datos.

Implementación

Variaciones
Las interfaces Strategy y Context deben permitir a una ConcreteStrategy acceder de manera eficiente a cualquier dato que
ésta necesite del contexto, y viceversa. Existen diversas opciones:

Un enfoque es que Context pase los datos como parámetros a las operaciones de Strategy, es decir, llevar los datos a la
estrategia. Esto mantiene a Strategy y Context desacoplados. El principal inconveniente de esta alternativa es que
Context podría pasar datos a la Strategy que ésta no necesita.

Otra técnica es que Context se pase a sí mismo como argumento, y que Strategy le pida los datos explícitamente al
contexto. Como alternativa, la estrategia puede guardar una referencia a su contexto, eliminando así la necesidad de pasar
nada. El principal inconveniente de este enfoque es que Context debe definir una interfaz más elaborada para sus datos, lo
que acopla más estrechamente a Strategy y Context.

Se pueden utilizar las plantillas para configurar una clase con una estrategia. Esta técnica solo es aplicable si se puede
seleccionar la estrategia en tiempo de compilación y no hay que cambiarla en tiempo de ejecución. En este caso, la clase
Context se define en una clase plantilla que tiene como parámetro una clase Strategy.

Se puede proporcionar en Context un comportamiento predeterminado y hacer opcionales los objetos Strategy.
Context comprueba si tiene un objeto Strategy antes de acceder a él y, en caso de que exista, lo usa normalmente. Pero, en
caso de que no tenga sentido tener un objeto Strategy y éste no exista, Context realiza el comportamiento
predeterminado. La ventaja de este enfoque es que los clientes solo tienen que tratar con los objetos Strategy cuando no les
sirva el comportamiento por defecto.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 101/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

Las jerarquías de clases Strategy definen una familia de algoritmos o El patrón tiene el
comportamientos para ser reutilizados por los contextos. La herencia puede inconveniente potencial de
ayudar a sacar factor común de la funcionalidad de estos algoritmos. que un cliente debe
comprender cómo difieren las
La herencia ofrece otra forma de permitir una variedad de algoritmos o
distintas ConcreteStrategy
comportamientos. Se puede heredar de Context para proporcionar diferentes
antes de seleccionar la
comportamientos, pero esto liga el comportamiento a Context, mezclando la
adecuada. Los clientes pueden
implementación del algoritmo con la de Context. Esto dificulta su comprensión,
estar expuestos a cuestiones de
mantenimiento y extensión e impide la modificación del algoritmo
implantación. Por tanto, debería
dinámicamente. El resultado será una gran cantidad de clases relacionadas cuya
usarse solo cuando la variación
única diferencia es el algoritmo o comportamiento que utilizan. Encapsular el
de comportamiento sea
algoritmo en clases Strategy separadas permite variar el algoritmo
relevante a los clientes.
independientemente de su contexto, haciendo este más fácil de cambiar,
comprender y extender. La interfaz de Strategy es
compartida por todas las clases
ConcreteStrategy, ya sea el
El patrón ofrece una alternativa a las sentencias condicionales para algoritmo que implementan
seleccionar el comportamiento deseado, ya que, en su ausencia, cuando se trivial o complejo. Por tanto, es
juntan muchos comportamientos en una clase es difícil no recurrir a éstas para probable que algunos objetos
seleccionar el comportamiento correcto. ConcreteStrategy no usen
toda la información que
Las estrategias permiten proporcionar distintas implementaciones del mismo
reciben a través de dicha
comportamiento. El cliente puede elegir entre estrategias con diferentes soluciones
interfaz; pudiendo darse el
de compromiso entre tiempo y espacio.
caso incluso de que las
estrategias concretas simples
no utilicen ninguna en
absoluto. Esto implica que
habrá ocasiones en las que el
contexto cree e inicialice
parámetros que nunca se usan.
Si esto puede ser un problema,
necesitaremos un acoplamiento
más fuerte entre Strategy y
Context.

El patrón aumenta el número


de objetos de una aplicación. A
veces se puede reducir este coste
si los objetos ConcreteStrategy
no tienen estado, pudiendo así
ser compartidos por el contexto.
Esto también es posible si, en
caso de necesitar cualquier
estado residual, es Context quien
se encarga de mantenerlo,
pasándoselo a ConcreteStrategy
en cada petición. Las estrategias
compartidas no deberían
mantener el estado entre
invocaciones. Cuando se
comparten las estrategias de este
modo, son en esencia objetos
FlyWeight que no tienen estado
intrínseco, sino solo
comportamiento.

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Encontrar objetos apropiados Cohesión Dependencias algorítmicas Acoplamiento

Especificar la Implementación de Objetos Implementación Añadir funcionalidad mediante herencia Principio


Abierto/Cerrado

Poner a funcionar los mecanismos de Reusabilidad por


reutilización composición,
herencia y/o
parametrización

Template Method
Problema

Motivación

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 102/117
19/1/2021 Patrones de Diseño

Un profesor se
Scenario
responsabiliza de
enseñar con el
main()
mismo algoritmo,
presentarse,
presentar el curso,
explicar los
contenidos, Student

responder las
attendCourse(Professor)
dudas, evaluar y
despedir el curso,
pero dependiendo
de la localización,
clase o campo o …, public teach() {
this.introduceYourself();
algunos pasos del
Professor this.introduceCourse();
algoritmo serán if (professorLocation == Location.CLASSROOM.ordinal())
variables ya que teach() this.explainSubjectInClassRoom();
los realizará de explainSubjectinClassRoom() else ifprofessorLocation == Location.FIELD.ordinal())
manera distinta,
explainSubjectinField() this.expandinSubjectInField();
assessInClassRoom() this.answerDoubts();
bien con distintos assessInField()
if (professorLocation == Location.CLASSROOM.ordinal())
recursos didácticos introduceYourself()
introduceCource()
this.assessInClassRoom();
(proyector o pizarra answerDoubts() else if (professorLocation == Location.FIELD.ordinal())
o …, Moodle o folio concludCourse() this.assessInField();
this.concludeCource();
o …) o con distinto
}
nivel de detalle
(exhaustivo o
superficial o …) , o Esto complica la comprensión de su comportamiento y tiende a crecer a medida que
… surgen nuevas opciones para los pasos variables.

Código de Contraejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/TemplateMethod/templateMethodWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 103/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Professor (ej. 0) es La cohesión de la La granularidad de la clase Professor (ej. 9)


nulo. clase Professor no depende de la cantidad de métodos
es adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume varias
Se calcula como la suma de los métodos
responsabilidades
relativos a la responsabilidad de la clase
dispares o que no
(ej. teach, 1) más los métodos relativos a los
le atañen, como el
pasos comunes del algoritmo (ej.
conocimiento de
introduceYourself, introduceCourse,
todos los posibles
answerDoubts y concludeCourse, 4) más el
pasos alternativos
producto de las localizaciones por los
del algoritmo
métodos relativos a los pasos alternativos
dependiendo de la
del algoritmo (ej. clase y campo, 2, por
localización.
explainSubject y assess, 2).

Su resultado es de orden cuadrático, O(n2).

Intención

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 104/117
19/1/2021 Patrones de Diseño

Si la
Scenario
responsabilidad
de profesor
main()
incluye
únicamente la
solicitud de
realizar los pasos
«Director»
variables y otros,
Student
profesores
concretos, se attendCourse(Professor)
responsabilizan
por separado de
cómo se realizan
los pasos «AbstractClass»
public teach() {
variables, ninguna Professor
this.introduceYourself();
clase será compleja this.introduceCourse();
teach()
y se evitará la explainSubject() this.explainSubject();
tendencia a crecer. assess() this.answerDoubts();
introduceYourself() this.assess();
introduceCource() this.concludeCource();
answerDoubts()
}
concludCourse()

«ConcreteClassA» «ConcreteClassB»
ProfessorInClassRoom ProfessorInField

explainSubject() explainSubject()
assess() assess()

Código de Ejemplo
(https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/TemplateMethod/templateMethodFine)

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Professor (ej. 0) es La cohesión de la La granularidad de la clase Professor (ej. 7)


nulo. clase Professor es depende de la cantidad de métodos
adecuada puesto requeridos.
Su resultado es de orden constante, O(1).
que asume una
Se calcula como la suma de los métodos
única
relativos a la responsabilidad de la clase
responsabilidad,
(ej. teach, 1) más los métodos relativos a los
centrada en los
pasos comunes del algoritmo (ej.
pasos comunes del
introduceYourself, introduceCourse,
algoritmo,
answerDoubts y concludeCourse, 4) más los
colaborando con el
métodos relativos a los pasos variables del
servicio de profesor
algoritmo (ej. explainSubject y assess, 2).
concreto que se
responsabiliza de Su resultado es de orden lineal, O(n ).
los pasos
alternativos del
algoritmo.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 105/117
19/1/2021 Patrones de Diseño

Intención Aplicabilidad

La intención de este patrón es Implementar las partes invariantes de un algoritmo, permitiendo que sean las
definir el esqueleto de un subclases quienes implementen el comportamiento que puede variar.
algoritmo en una operación,
Factorizar un comportamiento repetido de varias subclases para ubicarlo en una
difiriendo algunos pasos a las
clase común evitando así código duplicado.
subclases para que éstas
puedan redefinirlos sin Controlar la extensión de subclases en puntos específicos mediante la
cambiar la estructura. definición de un método plantilla que llame a operaciones vacías (conocidas
como operaciones de enganche), que puedan ser redefinidas por las subclases,
restringiendo así las extensiones de las mismas a estos puntos de enganche.

Solución

Estructura General Participantes

AbstractClass: declara una


Scenario
clase abstracta o interfaz que:

main() Define las operaciones


primitivas abstractas que son
implementadas por las
subclases para realizar los
pasos de un algoritmo.
Director

public templateMethod() {
AbstractClass ...
this.primitiveOperation1();
templateeMethod() ...
primitiveOperation1() this.primitiveOperation2();
primitiveOperation2() ...
}

ConcreteClassA ConcreteClassB

primitiveOperation1() primitiveOperation1()
primitiveOperation2() primitiveOperation2()

Se pueden identificar las operaciones que deberían ser redefinidas añadiendo un sufijo a su nombre, por ejemplo “do-”.

Se pueden declarar con visibilidad protegida para garantizar que solo puedan ser llamadas por el método plantilla.

Se debe minimizar el número de operaciones primitivas que una subclase debe redefinir para dar cuerpo al algoritmo.

Implementa un método plantilla que define el esqueleto de un algoritmo. Este método llama a las operaciones primitivas
abstractas, así como a operaciones definidas en AbstractClass u otras clases.

Se puede declarar como final para evitar que pueda ser redefinido.

ConcreteClass: clase derivada de AbstractClass que implementa las operaciones primitivas abstractas para realizar los
pasos del algoritmo específicos de las subclases.

Implementación

Variaciones
Las dos principales variantes del patrón Template Method son:

La clase AbstractClass es una clase abstracta y no proporciona una implementación para las operaciones primitivas
que declara. Requiere que las subclases definan una implementación porque no hay ningún comportamiento
predeterminado razonable.

La clase AbstractClass es una clase abstracta (menos común) o concreta y proporciona una implementación
predeterminada para las operaciones primitivas que declara. Estas operaciones se denominan operaciones de
enganche, y permiten controlar la extensión de subclases en puntos específicos. Una operación de enganche normalmente
no hace nada por omisión, por lo que es fundamental identificarlas convenientemente para que no sean obviadas.

Consecuencias

Ventajas Desventajas

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 106/117
19/1/2021 Patrones de Diseño

Ventajas Desventajas

Los métodos plantilla son una técnica fundamental de reutilización de código. Un número elevado de
operaciones primitivas que
Los métodos plantilla llevan a una estructura de control invertido, es decir, una
requieran ser redefinidas puede
clase padre llama a las operaciones de una subclase y no al revés. Los métodos
resultar tedioso para los clientes.
plantilla llaman a los siguientes tipos de operaciones primitivas:
Un objetivo importante para
Operaciones abstractas que deben ser obligatoriamente redefinidas por las diseñar métodos plantilla es
subclases. minimizar el número de
operaciones primitivas que una
subclase debe redefinir para dar
Operaciones concretas, ya sea de la ConcreteClass, de la AbstractClass, o de las cuerpo al algoritmo.
clases cliente.

Operaciones de enganche, que ofrecen un comportamiento predeterminado,


pero que pueden ser opcionalmente redefinidas por las subclases si es necesario.

Métodos de fabricación (ver patrón Factory Method).

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Poner a funcionar los mecanismos de Reusabilidad Dependencias algorítmicas Acoplamiento


reutilización por
composición,
herencia y/o
parametrización

Visitor
Problema

Motivación

Un paciente
cuando tiene un
accidente se
responsabiliza de
realizar distintas
actividades
médicas, evaluar
los daños,
diagnosticarse,
operarse, … sobre
las distintas
partes del cuerpo,
cabeza, tronco,
extremidad, …

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 107/117
19/1/2021 Patrones de Diseño

Scenario

main()

Hospital

treatPatient(Patient)

Patient

add(BodyPart)
evaluate()
diagnose()
operate()

BodyPart

evaluate()
diagnose()
operate()

Head Trunk Limb

evaluate() evaluate() evaluate()


diagnose() diagnose() diagnose()
operate() operate() operate()

public evaluate() { public evaluate() { public evaluate() {


// Evaluating head // Evaluating trunk // Evaluating limb
} } }

public diagnose() { public diagnose() { public diagnose() {


// Diagnosing head // Diagnosing trunk // Diagnosing limb
} } }

public operate() { public operate() { public operate() {


// Operating head // Operating trunk // Operating limb
} } }

Esto complica la comprensión de su comportamiento y tiende a crecer a medida que


surgen nuevas partes del cuerpo a tratar.

Código de Contraejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Visitor/visitorWrong)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 108/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Patient (ej. 1) La cohesión de la La granularidad de la clase Patient (ej. 4)


depende del tipo de partes del cuerpo (ej. clase Patient no es depende de la cantidad de métodos
BodyPart, 1). adecuada puesto requeridos.
que asume varias
Su resultado es de orden constante, O(1). Se calcula como la suma de los métodos
responsabilidades
relativos a la responsabilidad de la clase
dispares o que no
(ej. evaluate, diagnose y operate, 3) más el
le atañen, como el
método para añadir las partes del cuerpo
conocimiento de
(ej. addBodyPart, 1).
todas las posibles
actividades Su resultado es de orden lineal, O(n).
médicas a realizar
sobre las distintas
partes del cuerpo.

Intención

Si la
Scenario
responsabilidad
main()
del paciente
incluye
únicamente la
aceptación de la «Director»
Hospital
visita sobre las
treatPatient(Patient)
distintas partes
del cuerpo por el
personal del
«Visitor»
hospital y otros, el Staff
«ObjectStructure»
Patient
personal del
visitHead(Head)
hospital, se visitTrunk(Trunk)
add(BodyPart)
accept(Staff)
visitLimb(Limb)
responsabilizan
por separado de
cómo se realizan
«ConcreteVisitirB» «ConcreteVisitirC» «ConcreteVisitirA»
las distintas Doctor Surgeon TriageNurse «Element»
actividades BodyPart
visitHead(Head) visitHead(Head) visitHead(Head)
médicas sobre visitTrunk(Trunk) visitTrunk(Trunk) visitTrunk(Trunk) accept(Staff)
visitLimb(Limb) visitLimb(Limb) visitLimb(Limb)
cada parte del
cuerpo del
paciente, ninguna
«ConcreteElementA» «ConcreteElementB» «ConcreteElementC»
clase será compleja Head Trunk Limb
y se evitará la
accept(Staff) accept(Staff) accept(Staff)
tendencia a crecer.

public accept(Staff) { public accept(Staff) { public accept(Staff) {


staff.visitHead(this); staff.visitTrunk(this); staff.visitLimb(this);
} } }

Código de Ejemplo (https://github.com/USantaTecla-disenyo/designPatterns/tree/master/src/main/java/usantatecla/Visitor/visitorFine)

Acoplamiento Cohesión Granularidad

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 109/117
19/1/2021 Patrones de Diseño

Acoplamiento Cohesión Granularidad

El acoplamiento de la clase Patient (ej. 2) La cohesión de la La granularidad de la clase Patient (ej. 2)


depende del tipo de partes del cuerpo (ej. clase Patient es depende de la cantidad de métodos
BodyPart, 1) y del tipo de personal del adecuada puesto requeridos.
hospital (ej. Staff, 1). que asume una
única
Su resultado es de orden constante, O(1).
responsabilidad, Se calcula como la suma del método
centrada en relativo a aceptar las visitas del tipo del
aceptar la visita del personal del hospital (ej. accept, 1) más el
personal del método para añadir las partes del cuerpo
hospital, (ej. addBodyPart, 1).
colaborando con el
Su resultado es de orden constante, O(1).
servicio de
personal que se
responsabiliza de
realizar las
actividades
médicas sobre las
distintas partes del
cuerpo.

Intención Aplicabilidad

La intención de este patrón es Una estructura de objetos contiene muchas clases de objetos con diferentes
representar una operación a interfaces y se quiere realizar operaciones sobre esos elementos que
realizar sobre los elementos dependen de la clase concreta.
de una estructura de objetos,
Se necesita realizar muchas operaciones distintas y no relacionadas sobre
permitiendo definir nuevas
objetos de una estructura de objetos y se quiere evitar “contaminar” sus clases
operaciones sin cambiar las
con dichas operaciones. El patrón Visitor permite mantener juntas operaciones
clases los de elementos sobre
relacionadas definiéndolas en una clase. Cuando la estructura de objetos es
los que opera.
compartida por varias aplicaciones, el patrón Visitor permite poner operaciones
sólo en aquellas aplicaciones que las necesitan.

Las clases que definen la estructura de objetos rara vez cambian, pero muchas
veces se quiere definir nuevas operaciones sobre la estructura. Cambiar las
clases de la estructura de objetos requiere redefinir la interfaz para todos los
visitantes, lo que es potencialmente costoso. Si las clases de la estructura cambian
con frecuencia, probablemente sea mejor definir las operaciones en las propias
clases.

Solución

Estructura General Participantes

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 110/117
19/1/2021 Patrones de Diseño

Estructura General Participantes

Visitor: declara una clase


Scenario
abstracta o interfaz que define
main()
una operación visit para cada
clase ConcreteElement de la
estructura de objetos. El nombre
Director
y/o signatura de la operación
identifican a la clase que envía
la petición visit al visitante. Esto
permite al visitante determinar
la clase concreta de elemento
Visitor
ObjectStructure que está siendo visitada,
visitConcreteElementA(ConcreteElementA) pudiendo así acceder al
visitConcreteElementB(ConcreteElementB)
elemento directamente a través
de su interfaz particular.

ConcreteVisitirA ConcreteVisitirB
Element

visitConcreteElementA(ConcreteElementA) visitConcreteElementA(ConcreteElementA)
accept(Visitor)
visitConcreteElementB(ConcreteElementB) visitConcreteElementB(ConcreteElementB)

ConcreteElementA ConcreteElementB

accept(Visitor) accept(Visitor)
operationA() operationA()

public accept(Visitor) { public accept(Visitor) {


visitor.visitConcreteElementA(this); visitor.visitConcreteElementB(this);
} }

ConcreteVisitor: clase derivada de Visitor que implementa las operaciones visit definidas en la interfaz. Cada clase
ConcreteVisitor representa una operación específica del sistema, y cada operación visit implementa el comportamiento
específico del visitante para la clase ConcreteElement correspondiente. ConcreteVisitor proporciona el contexto para el
algoritmo y guarda su estado local. Muchas veces este estado acumula resultados durante el recorrido de la estructura.

Element: declara una clase abstracta o interfaz que define una operación accept que recibe un Visitor como argumento. La
clase Element representa los objetos sobre los que actúa Visitor.

ConcreteElement: clase derivada de Element que implementa la operación accept definida en la interfaz invocando al
método visit apropiado definido en Visitor. Cada clase ConcreteElement representa una entidad específica del sistema.

ObjectStructure: clase que consta de una serie de elementos y que:

Define una interfaz para enumerar sus elementos.

Puede proporcionar una interfaz de alto nivel para permitir al visitante visitar a sus elementos.

Puede ser una clase Composite o una colección, como una lista o un conjunto.

Implementación

Variaciones
El patrón Visitor permite añadir operaciones a clases sin modificar éstas. Esto se logra mediante la técnica de doble-
despacho, llamada así porque la operación que se ejecuta depende del tipo de solicitud y de los tipos de dos receptores.

Accept es una operación de doble-despacho, puesto que su significado depende de dos tipos: el del Visitor y el del
Element. El doble-despacho permite a los ConcreteVisitor solicitar diferentes operaciones en cada clase ConcreteElement.

Esta es la clave del patrón Visitor: la operación que se ejecuta depende tanto del tipo de Visitor como del tipo de
Element visitado. En vez de enlazar operaciones estáticamente en la interfaz de Element, se pueden fusionar las
operaciones en un Visitor y usar accept para hacer el enlace en tiempo de ejecución. Extender la interfaz de Element
consiste en definir una nueva subclase de Visitor en vez de muchas nuevas subclases de Element.

El algoritmo de recorrido que un visitante debe utilizar para visitar cada elemento de la estructura de objetos puede
ser definido en la estructura de objetos, en un objeto iterador aparte o en el visitante:

En muchas ocasiones es la propia estructura de objetos la responsable de la iteración. Una colección simplemente
iterará sobre sus elementos, llamando a la operación accept de cada elemento. Un objeto Composite generalmente se
recorrerá a sí mismo haciendo que cada operación accept recorra los hijos del elemento y llame a accept sobre cada uno de
ellos recursivamente.

Otra solución es utilizar un iterador para visitar los elementos, bien sea externo o interno, dependiendo de la
disponibilidad y la eficiencia.

Puesto que los iteradores internos son implementados por la estructura de objetos, usar un iterador interno es muy
similar a que sea la estructura de objetos la responsable de la iteración. La principal diferencia estriba en que un iterador
interno no provocará un doble-despacho, sino que llamará a una operación del visitante con un elemento como
argumento, frente a llamar a una operación del elemento con el visitante como argumento. Pero resulta sencillo usar el
patrón Visitor con un iterador interno si la operación del visitante simplemente llama a la operación del elemento sin
recursividad.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 111/117
19/1/2021 Patrones de Diseño

Otra alternativa consiste en ubicar el algoritmo de recorrido en el visitante, si bien en ese caso se duplica el código del
recorrido en cada ConcreteVisitor para cada agregado ConcreteElement. La principal razón para seguir este enfoque es
poder implementar un recorrido especialmente complejo que dependa de los resultados de las operaciones realizadas sobre
la estructura de objetos.

Consecuencias

Ventajas Desventajas

Los visitantes facilitan añadir nuevas operaciones que dependen de los El patrón Visitor hace que sea
componentes de objetos complejos. Se puede definir una nueva operación sobre complicado añadir nuevas
una estructura simplemente añadiendo un nuevo visitante. Si, por el contrario, subclases ConcreteElement, ya
extendiésemos la funcionalidad sobre muchas clases, habría que cambiar cada clase que cada nueva clase
para definir una nueva operación. ConcreteElement da lugar a una
nueva operación abstracta de
El comportamiento similar no está desperdigado por las clases que definen la
Visitor y a su correspondiente
estructura de objetos; sino que está localizado en un visitante. Las partes de
implementación en cada clase
comportamiento no relacionadas se dividen en sus propias subclases del visitante.
ConcreteVisitor. A veces se
Esto simplifica tanto las clases que definen los elementos como los algoritmos
puede proporcionar en Visitor
definidos por los visitantes. Cualquier estructura de datos específica de un algoritmo
una implementación
puede estar oculta en el visitante.
predeterminada que puede
Los visitantes pueden acumular estado a medida que van visitando cada ser heredada por la mayoría
elemento de la estructura de objetos. Sin un visitante, este estado se pasaría como de los ConcreteVisitor, pero
argumentos extra a las operaciones que realizan el recorrido, o quizá como esto representa una excepción
variables globales. más que una regla.

Por tanto, la cuestión


fundamental a considerar a la
hora de aplicar el patrón
Visitor es si es más probable
que cambie el algoritmo
aplicado sobre una
estructura de objetos o las
clases de los objetos que
componen la estructura. La
jerarquía de clases Visitor
puede ser difícil de mantener
cuando se añaden nuevas
clases de ConcreteElement con
frecuencia.

Si se utiliza un iterador para


visitar a los objetos de una
estructura llamando a sus
operaciones a medida que los
recorre, como un iterador no
puede trabajar en varias
estructuras de objetos con
distintos elementos, esto implica
que todos los elementos que el
iterador puede visitar deben
tener una clase padre común
Element.

Se impone en este caso una


restricción que el patrón
Visitor no tiene, puesto que
en el patrón se pueden
visitar objetos que no
tienen una clase padre
común, ya que se puede
añadir cualquier tipo de
objeto a la interfaz de
Visitor.

El enfoque del patrón Visitor


asume que la interfaz de
ConcreteElement es lo
bastante potente como para
que los visitantes hagan su
trabajo. Como resultado, el
patrón suele obligarnos a
proporcionar operaciones
públicas que acceden al estado
interno de un elemento, lo que
puede comprometer su
encapsulación.

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 112/117
19/1/2021 Patrones de Diseño

Problemas de Diseño y Rediseño

Problemas de Diseño Problemas de Rediseño

Determinar la granularidad de los objetos Tamaño Dependencias algorítmicas Acoplamiento

Especificar interfaces de objetos Abstracción Incapacidad para modificar las clases Principio
convenientemente Abierto/Cerrado

Poner a funcionar los mecanismos de Reusabilidad


reutilización por
composición,
herencia y/o
parametrización

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 113/117
19/1/2021 Patrones de Diseño

Relaciones
chainofResponsability Mediator Adapter Proxy

Command Interpreter Observer

Builder Bridge Composite Strategy State

abstractFactory Memento Decorator Iterator Visitor Flyweight

Facade Prototype factoryMethod

Singleton templateMethod

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 114/117
19/1/2021 Patrones de Diseño

Aplicación
Selección Uso

Valorar cómo los patrones de diseño Poner atención particular a la aplicabilidad


ayudan a encontrar objetos, determinar Leer el patrón como una visión general y consecuencias para asegurar que el patrón
la granularidad de los objetos, es el correcto para el problema
Considerar cómo los patrones
especificar las interfaces de los objetos
de diseño resuelven problemas
y otras más. Haciendo referencia a este
aspecto puede ayudar a encontrar el Asegurar que se comprenden las clases y
Estudiar las secciones de Estructura,
patrón correcto objetos del patrón y cómo se relacionan
Participantes y Colaboradores
entre ellos
Leer la intención de cada patrón para
Analizar las secciones de Intención encontrar uno o más que parecen relevantes
para el problema Leer la sección de Código de Ejemplo
Estudiar el código ayuda a aprender a
para ver un ejemplo concreto
cómo implementar el patrón
del patrón en código
Estas relaciones pueden ayudar directamente
Estudiar cómo los patrones
a seleccionar el patrón o conjunto
se interrelacionan Los nombre de los participantes en
de patrones correcto
los patrones de diseño son generalmente
demasiado abstractos para aparecer
Profundiza en las similaridades y
directamente en una aplicación. En cambio,
Estudiar el Propósito de los patrones diferencias entre los propósitos
es útil incorporar el nombre de
de los patrones Elegir nombre para los participantes
los participantes en el nombre que aparece
del patrón que sean significativos
en la solicitud. Eso ayuda a que el patrón
Empezar observando si el problema involucra en el contexto de la aplicación
sea más explícito en la aplicación. Por ejemplo,
uno o más causas. Entonces, buscar si se utiliza el patrón de Strategy para
Examina las causas de re-diseño
los patrones que ayuden a evitar las un algoritmo de composición de textos,
causas de re-diseño entonces es posible tener clases
SimpleLayoutStrategy o TeXLayoutStrategy
Este enfoque es el opuesto al enfoque
de las causas de re-diseño. En vez de
Declarar su interfaz, establecer sus
considerar lo que podría forzar un cambio
relaciones de herencia y definir
Considera que sería variable en el diseño de diseño, considera qué se quiere ser capaz
las variables de instancia que representan
de cambiar sin re-diseño. Este enfoque
Definir las clases los datos y referencias a objetos</b>.
se apoya en la encapsulación de lo que varía,
Identificar clases existentes en la
un aspecto de muchos patrones
aplicación que el patrón afecta y
modificarlas acordemente

Otra vez, los nombres generalmente


dependen de la aplicación. Usar
las responsabilidades y colaboraciones
Definir nombres específicos de asociadas con cada operación como guía.
la aplicación para las operaciones También, ser consistentes en las
en el patrón convenciones de nombrado. Por ejemplo,
se podría usar el prefijo “créate”
consistentemente para denotar un
método factoría

La sección de Implementación ofrece


Implementar las operaciones que
pistas para guiar la implementación.
lleven a cabo las responsabilidades
La sección de Código de Ejemplo
y colaboraciones en el patrón
también puede ayudar

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 115/117
19/1/2021 Patrones de Diseño

Bibliografía
Obra, Autor y Edición Portada Obra, Autor y Edición Portada

Object Solutions. Object Oriented Analysis


Managing the Object and Design with
Oriented Project Applications

Grady Booch Grady Booch

Addison-Wesley Imprint Addison-


Professional (1789) Wesley Educational s
Inc (3 de junio de 2011)

The Unified Modeling The Mythical Man Month.


Language User Guide Essays on Software
Engineering
Grady Booch
Frederick P. Brooks
Pearson Education
(US); Edición: 2 ed (28 Prentice Hall; Edición:
de junio de 2005) Nachdr. 20th
Anniversary (1 de
enero de 1995)

Extreme Programming Refactoring. Improving


Explained. Embrace the Design of Existing
Change. Embracing Code
Change
Martin Fowler,Kent
Kent Beck,Cynthia Beck,John
Andres Brant,William
Opdyke,Don Roberts
Addison-Wesley
Educational Publishers Addison Wesley;
Inc; Edición: 2nd Edición: 01 (1 de
edition (16 de octubre de 1999)
noviembre de 2004)

UML Distilled. A Brief Patrones de diseño


Guide to the Standard
Erich Gamma et al
Object Modeling
Language Grupo Anaya
Publicaciones
Martin
Generales; Edición: 1 (1
Fowler,Kendall Scott
de noviembre de 2002)
Addison-Wesley
Educational Publishers
Inc; Edición: 3 ed (15 de
septiembre de 2003)

Clean Code. A Handbook Object-Oriented Software


of Agile Software Construction
Craftsmanship
Bertrand Meyer
Robert C. Martin
Prentice Hall; Edición:
Prentice Hall; Edición: 2 ed (3 de abril de
01 (1 de agosto de 2008) 1997)

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 116/117
19/1/2021 Patrones de Diseño

Ponente
Luis Fernández Muñoz Doctor en Inteligencia Artificial por
la UPM
Formador/Consultor
Ingeniero en Informática por la
Linkedin (https://es.linkedin.com/in/luisfernandezmunyoz)
UMA

Diplomado en Informática por la


UPM

Profesor Titular de ETSISI de la


UPM

Version 0.0.1
Last updated 2020-12-10 10:12:37 +0100

file:///C:/USantaTecla/itinerario/x-publicaciones/USantaTecla/2-disenyo/4-patronesDisenyo/index.html 117/117

También podría gustarte