2. • El diseño es un modelo del sistema, realizado
con una serie de principios y técnicas, que
permite describir el sistema con el suficiente
detalle como para ser implementado.
• Estos esquemas y estructuras son conceptos
reusables y nos permiten no reinventar la
rueda. Un buen ingeniero reutiliza un
esquema de solución ante problemas
similares.
3. CONCEPTO
• "Una arquitectura orientada a objetos bien
estructurada está llena de patrones. La calidad
de un sistema orientado a objetos se mide por
la atención que los diseñadores han prestado
a las colaboraciones entre sus objetos. Los
patrones conducen a arquitecturas más
pequeñas, más simples y más comprensibles".
(Grady Booch)
4. Historia
• El concepto de "patrón de diseño" que tenemos en
Ingeniería del Software se ha tomado prestado de la
arquitectura. En 1977 se publica el libro "A Pattern
Language: Towns/Building/Construction", de Christopher
Alexander, Sara Ishikawa, Murray Silverstein, Max
Jacobson, Ingrid Fiksdahl-King y Shlomo Angel, Oxford
University Press. Contiene numerosos patrones con una
notación específica de Alexander.
• Alexander comenta que “Cada patrón describe un
problema que ocurre una y otra vez en nuestro
entorno, para describir después el núcleo de la solución
a ese problema, de tal manera que esa solución pueda
ser usada más de un millón de veces sin hacerlo siquiera
dos veces de la misma forma”. El patrón es un esquema
de solución que se aplica a un tipo de problema, esta
aplicación del patrón no es mecánica, sino que requiere
de adaptación y matices. Por ello, dice Alexander que
los numerosos usos de un patrón no se repiten dos veces
de la misma forma.
• La idea de patrones de diseño estaba "en el aire", la
prueba es que numerosos diseñadores se dirigieron a
aplicar las ideas de Alexander a su contexto. El catálogo
más famoso de patrones se encuentra en “Design
Patterns: Elements of Reusable Object-Oriented
Software”, de Erich Gamma, Richard Helm, Ralph
Johnson y John Vlissides, 1995, Addison-Wesley,
también conocido como el libro GOF (Gang-Of-Four).
• Siguiendo el libro de GOF los patrones se clasifican
según el proposito para el que han sido definidos:
• Creacionales: solucionan problemas de creación de
instancias. Nos ayudan a encapsular y abstraer dicha
creación.
• Estructurales: solucionan problemas de composición
(agregación) de clases y objetos.
• De Comportamiento: soluciones respecto a la interacción
y responsabilidades entre clases y objetos, así como los
algoritmos que encapsulan.
5. Pasos para describir un caso
• Nombre
• Propósito o finalidad
• Sinónimos (otros nombres por
los que puede ser conocido)
• Los patrones de diseño son
descripciones de clases cuyas • Problema al que es aplicable
instancias colaboran entre sí. Cada • Estructura (diagrama de clases)
patrón es adecuado para ser • Participantes (responsabilidad
adaptado a un cierto tipo de de cada clase)
problema. • Colaboraciones (diagrama de
interacciones)
• Implementación
(consejos, notas y ejemplos)
• Otros patrones con los que está
relacionado
6. Tipos de Patrones que se manejan en
Java
• A continuación veremos • Creación, patrones para
la aplicación de patrones crear objetos
de diseño en Java, • Comportamiento,
normalmente se puede patrones para coordinar
leer mucho al respecto, la interacción funcional
pero lo que realmente entre objetos
interesa es saber cuándo • Estructural, patrones para
utilizarlos y cómo se manejar relaciones
terminan implementando estáticas y estructurales
estos conceptos. entre objetos
• Sistema, patrones para
manejar la interacción a
nivel de sistema
7. Patrones de Creación
• Este tipo de patrones soporta una de las tareas
más comunes en la programación orientada a
objetos, la creación de objetos en un sistema.
Algunos patrones de este tipo son:
• Abstract factory
• Builder
• Factory Method
• Prototype
• Singleton
8. PATRON FACTORY
• Define una interface
para crear objetos,
dejando a las
subclases decidir la
clase específica.
Permite delegar la
responsabilidad de la
instanciación a las
subclases.
Ventajas: Factory Methods elimina la necesidad de asociar aplicación-
clases específicas en el código. Sólo trabajamos con interfaces.
9. Ejemplo
• Se nos encarga crear un traductor que
devuelva los números del cero al diez en tres
idiomas: inglés, español, y alemán. Existen
muchísimas maneras de hacer esto. Al final, se
desea un método que reciba un entero entre 0
y 10 y que devuelva una cadena con el
nombre de dicho número en el idioma que se
esté trabajando.
10. Una manera de entrarle al problema podría ser
algo así:
11. • Esta solución parece funcionar,
y de hecho lo hace. Pero
imaginemos que ahora nos
dicen que desean la
traducción de todos los
números? Sin duda el código
comenzará a crecer. Y claro,
ahora tendremos que agregar
código de lógica para cada
idioma para escribir números
como 752, 1233, etc.
• Como nos gusta hacer gala de
nuestro enfoque a objetos, los
primero que se nos ocurre es
una herencia. Definiremos una
clase abstracta Traductor, y
para cada idioma haremos una
subclase de Traductor.
12. • Vamos a crear una
clase especializada
para diccionario, que
se encargará de
traducir los números.
Tendremos una clase
especializada para
traducir los números
al español, que iría
algo así:
14. • Ahora, en el momento de querer utilizar un
diccionario, se llamaría algo así
15. Entonces, la clase MainClient
cambiaría un poco y quedaría así:
16. Qué hemos ganado?
• Primero, nuestro código es mucho más legible. Segundo es bastante
más escalable. Podemos agregar el traductor para el francés muy
fácilmente. Tercero hemos escondido la manera en la que
traducimos a Tradúceme. Por ejemplo, puede ser que las
traducciones a chino las vayamos a traer a un web Service. En ese
caso TraductorChino se encargaría de hacer todo el ajetreo de
conectarse a internet y buscar el web services, pero los demás ni se
enteran.
• Pero el Factory Pattern no ha aperecido, Es tiempo de irlo a llamar.
Bueno, Traduceme está haciendo algo que no le compete: está
eligiendo la instancia de Traductor que quiere usar. Imaginen que se
usa el traductor en 100 lugares, entonces en cien lugares se tiene
que buscar qué clase de Traductor vamos a instanciar. El patrón de
fábrica -factory pattern- nos esconde esa lógica. Vamos a agregar
ahora nuestra fábrica de traductores.
17.
18. • ¿Qué hace TraductorFactory? Simplemente
elige, en base a los argumentos dados – en este
caso el idioma- qué clase de traductor se
instanciará. Traduceme de nuevo cambia y
quedaría así:
19. • MainClient se ha visto dramáticamente reducido, y su código es muy fácil
de leer. Quien quiera usar un traductor simplemente hará llamar a
Traduceme. Traduceme sabe el idioma que eligieron, pero no sabe que
subclase de Traductor instanciar, pero sabiendo el idioma
TraductorFactory sabe exáctamente qué instancia de Traductor crear. Si la
aplicación desea cambiar de idioma simplemente le envía otro parámetro
a Traduceme y listo. También agregar idiomas es más manejable que
antes.
• El Factory Pattern esconde al usuario final dle código la desición de qué
sublclase instanciar, y promueve el encapsulamiento de las partes más
variables del sistema. En términos generales, una fábrica abstracta
consiste de las siguientes partes:
• Un cliente, que es el que llama a la fábrica (en nuestro caso MainClient).
• Una fábrica, que decidé la clase a instanciar (TraductorFactory).
• Un prodicto, lo que la fábrica devuelve (para nosotros las instancias de
Traductor).