Академический Документы
Профессиональный Документы
Культура Документы
Daniel Mazzini
dmazzini@ubicasolutions.com
Ubica Solutions
Conocimientos previos
Conocimientos de POO.
UML (básico)
C#
Daniel Mazzini
Agenda
Propósito de los patrones
Fundamentos de diseño.
•Creación. •Estructurales
–Factory Method –Adapter
–Singleton –Facade
–Abstract Factory –Composite
•Comportamiento
–Command
–State
–Observer
Daniel Mazzini
Propósito de los patrones
¿Qué es un patrón de diseño?
¿Por qué usarlos?
Categorización
Problema - Patrón
Daniel Mazzini
¿Qué es un patrón de diseño?
Ante un problema reiterado ofrece una
solución contrastada que lo resuelve.
Describe el problema en forma sencilla.
Describe el contexto en que ocurre.
Describe los pasos a seguir.
Describe los puntos fuertes y débiles de la
solución.
Describe otros patrones asociados.
Daniel Mazzini
¿Por qué usarlos?
Mejora en la comunicación y documentación
“Hay que hacer un Factory Method”
Facilita la documentación interna del proyecto.
Mejora la ingeniería de software.
Eleva el nivel del grupo de desarrollo.
Previene “reinventar la rueda” en diseño
Son soluciones ya probadas.
Mejora la calidad y estructura
“¿Cuan grande debe ser una clase?”
Daniel Mazzini
Categorización
Fundamentales
Se usan en otros patrones mas grandes
Creación
Aislar el proceso de creación de un objeto.
Estructura
Desacopla el sistema.
Comportamiento
Describe situaciones de control de flujo.
Daniel Mazzini
Problema - Patrón
Crear un objeto sin especificar la clase a la
que pertenece
Abstract Factory
Factory Method
Prototype
Dependencia para tareas especificas
Command
Cadena de Responsabilidad
Daniel Mazzini
Problema – Patrón (cont)
Dependencia hacia el hardware o software
Abstract Factory
Bridge
Dependencia hacia los algoritmos
Strategy
Template Method
Builder
Daniel Mazzini
Problema – Patrón (cont)
Alto acoplamiento
Façade
Mediator
Observer
Imposibilidad de cambiar la clases
convenientemente
Adapter
Decorator
Visitor
Daniel Mazzini
Fundamentos de diseño
Programar para las interfaz, no para la
herencia.
Favorecer la composición antes que la
herencia.
Delegación.
Doble Herencia.
Daniel Mazzini
Herencia o interfaz
La herencia de clase define la
implementación de una clase a partir de
otra (excepto métodos abstractos)
La herencia de interfaz define como se
llamara el método o propiedad, pudiendo
escribir distinto código en cada clase.
Daniel Mazzini
Programar para las interfaz
Reutilizar la implementación de la clase
base es la mitad de la historia.
Ventajas:
Reducción de dependencias.
El cliente desconoce la implementación.
La vinculación se realiza en tiempo de
ejecución.
Da consistencia (contrato).
Desventaja:
Indireccionamiento.
Daniel Mazzini
Favorecer la composición
Ventajas de la herencia:
Implementación ya realizada.
Útil en situaciones “es un”
Desventajas de usar herencia:
Construir un monstruo.
No se puede cambiar la implementación
heredada en tiempo de ejecución.
Quebrar la encapsulación.
Visibilidad.
Daniel Mazzini
Favorecer la composición (cont)
Ventajas de la composición:
Crear una nueva clase ensamblando con mas
de una clase.
Puede cambiar la clase con la cual ensamblo
en tiempo de ejecución.
Centrar cada clase en una tarea.
Desventaja de la composición:
Requiere escribir un poco mas de código.
Indireccionamiento.
Daniel Mazzini
Delegación
Una forma de componer.
Se delega un conjunto de operaciones de
un objeto en otro objeto.
“La herencia” que use en VB6.
+operacion() 1 1 +operacion()
return Delegado.operacion()
Daniel Mazzini
Anti-Ejemplo
Ventana
Nuevo requerimiento:
No todos las ventanas son cuadradas
Rectangulo
-Ancho : double
-Alto : double return Ancho * Alto
+Area()
Daniel Mazzini
Ejemplo de Delegado
• Quito la herencia en Ventana
return ISuperficie.Area();
ventana
+Area() : double
• Creo una interfaz para
comunicar el delegador
con el delegado «interface»
ISuperficie
• Creo un método llamado +Area() : double
Area en Ventana (solo
para mantener Rectangulo Circulo
compatibilidad) -Ancho : double -Radio : double
-Alto : double +Area() : double
• Llamo al método de la +Area() : double
interfaz que me da el área
return Pi * (Radio^2);
return Ancho * Alto;
Daniel Mazzini
Daniel Mazzini
Delegado en .Net
NumberComparer DateComparer
Daniel Mazzini
Doble Herencia
Problema:
Mantener las clases que implementan como
internas del proyecto (internal o Friend), pero
la interfaz pública.
Organizar clases que tienen un
comportamiento parecido para que sea
consistente.
Daniel Mazzini
Doble Herencia (cont)
Daniel Mazzini
Doble Herencia en .NET
«interface»
IDataAdapter
+Fill()
+FillSchema()
+...()
DataAdapter
+Fill()
+FillSchema()
+...()
SQLDataAdapter OLEBDDataAdapter
+Fill() +Fill()
+FillSchema() +FillSchema()
+...() +...()
Daniel Mazzini
Patrones de creación
Propósito:
Crear un objeto es una toma de decisión.
Separar los procesos de creación de objeto y
de uso de un objeto.
Cuales veremos?
Factory Method
Singleton
Abstract Factory
Daniel Mazzini
Factory Method
Problema:
La instancia del objeto a crear depende de
condiciones externas a la clase cliente.
Puede cambiar independientemente de
cambiar la clase cliente.
Ya he creado la estructura con “Doble
Herencia”, pero ahora necesito poder crear
una instancia de cualquier clase concreta.
Daniel Mazzini
Factory Method
Cliente Editar «interface»
IDataAdapter
Crear +Fill()
+FillSchema()
+...()
«interface»
IFactoriaDataAdapter
+CrearDataAdapter(in tipo : int) : IDataAdapter
DataAdapter
FactoriaDataAdapter +Fill()
+FillSchema()
+...()
+CrearDataAdapter(in tipo : int) : IDataAdapter
Crear
SQLDataAdapter OLEBDDataAdapter
+Fill() +Fill()
+FillSchema() +FillSchema()
+...() +...()
Daniel Mazzini
Daniel Mazzini
F.M. con Constructor Estático
Cliente Usar
«interface»
ICryptoTransform
Crear
HashAlgorithm
+Create(in tipo : string) : HashAlgorithm
•Método estático en
clase abstracta que
retorno instancias.
• Constructores privados
o protegidos. MD5 SHA1 SHA256
#MD5() #SHA1() #SHA256()
Daniel Mazzini
Daniel Mazzini
Singleton
Problema:
No se puede tener mas de una instancia de
una clase.
Se necesita controlar el acceso a una clase.
Daniel Mazzini
Singleton
• Cambio el constructor a privado. ClaseUnica
• Hago que la clase no pueda ser -instancia : ClaseUnica
heredada. -ClaseUnica()
+ObtenerInstancia() : ClaseUnica
• Agrego una variable estática del +Operacion1()
mismo tipo de la clase donde
esta contenida. (instancia)
• Agrego un método estático que if (instancia==null)
if (instancia==null)
instancia = new ClaseUnica();
retorne la variable estática. return instancia; {
Mutex mutex = new Mutex();
(GetInstance) mutex.WaitOne();
if(instancia==null)
• No creo el objeto hasta que sea instancia = new ClaseUnica();
mutex.Close();
necesario (Lazy Creation) }
return instancia;
• Agrego el código necesario para
no crear dos instancias en
distintos thread. Daniel Mazzini
Daniel Mazzini
Abstract Factory
Problema
Necesito crear una familia de objetos.
Trabajo con mas de una familia.
No puedo combinar ítems de las familias de
objetos.
El resto del sistema debe trabaja sin distinguir
entre familias de objetos.
Daniel Mazzini
Abstract Factory
TourDeFrancia ParisDakar
GP de Catalunya Carrera
F1 Circuito Montmelo
Movil Trazado
Monoplaza Rueda F1
Chasis Rueda
Daniel Mazzini
Carrera
+CrearMovil(Chasis,Rueda[]):Movil
+CrearRueda():Rueda
+CrearChasis():Chasis
+CrearTrazado():Trazado
TourDeFrancia Ruedas CrearRueda() {
+CrearMovil(Chasis,Rueda[]):Movil
return new Rueda26();
+CrearRueda():Rueda
+CrearChasis():Chasis }
+CrearTrazado():Trazado
Daniel Mazzini
Daniel Mazzini
Patrones de estructura
Propósito:
Desacoplar el sistema.
Obtener una estructura flexible.
Organizar.
Cuales veremos?
Adapter
Facade
Composite
Daniel Mazzini
Facade
Problemas:
El cliente hace muchos viajes al servidor.
Separe por capas, pero tengo muchas clases
públicas en el servidor para que puedan ser
creadas desde el cliente.
Necesito estructurar las llamadas desde el
cliente.
Daniel Mazzini
Facade
Form Cliente
Presentación Lógica
Daniel Mazzini
Facade
Cliente A B C Cliente Facade A B C
F.M
A.M A.M
B.M B.M
C.M C.M
Daniel Mazzini
Facade
Caso de Uso = Facade
Un caso de uso es lo interacción de un actor
con el sistema. La métodos de la fachada
encapsulan los pasos necesarios para llevar a
cabo lo que el cliente desea hacer.
Login
SistemaFacturacion
Cliente
Daniel Mazzini
Daniel Mazzini
Adapter
Problemas:
Necesitamos llamar a un método a través de
una interfaz para no tener dependencia en el
cliente.
La librería a la que hay que llamar no es
nuestra y no implementa esa interfaz.
No contamos con el código fuente de la
librería.
Daniel Mazzini
Adapter
Cliente IOperacion
+Operacion()
Externa
+DiferenteNombre()
Daniel Mazzini
Daniel Mazzini
Composite
Problema:
Estructuras de árbol o estructuras 1-N.
Tiene un objeto complejo que hay que
descomponer en partes.
Nodos especiales que pueden contener otros
nodos.
Daniel Mazzini
Composite
Espec Rojos = new ColorEsp(Color.Red);
Almacén ArrayList prodRojos =alm.Seleccionar(Rojos);
Espec RojoPeq =
-Productos():ArrayList Espec
newPeq = new TamañoEsp(Tamaño.Pequeño);
CompuestoAndEsp(
+Seleccionar(Especificacion):ArrayList ArrayList prodPeq = alm.Seleccionar(Peq);
new ColorEsp(Color.Red),
new TamañoEsp(Tamaño.Pequeño));
ArrayList prodRojos =alm.Seleccionar(RojoPeq);
Especificación
+EstaOK(Producto):bool
return (_espec1.EstaOK(Producto)
&& _espec2.EstaOK(Producto));
Daniel Mazzini
Composite
Espec[] ar = new Espec[] {
Almacén new ColorEsp(Color.Red),
-Productos():ArrayList
new TamañoEsp(Tamaño.Pequeño)};
+Seleccionar(Especificacion):ArrayList Espec ExpresionOr = new CompOrEsp(ar);
ArrayList prodRojos =alm.Seleccionar(ExpresionOr);
Especificación
+EstaOK(Producto):bool
Lista
CompAndEsp CompOrEsp
+CompAndEsp(Espec[]) +CompOrEsp(Espec[])
+EstaOK(Producto):bool +EstaOK(Producto):bool
Daniel Mazzini
Daniel Mazzini
Composite Dinámico
Empleado
+Agregar(Empleado)
+Quitar(Empleado)
+ObtenerSueldos():double
NodosHojas NodosPadre
+Agregar(Empleado) +Agregar(Empleado)
+Quitar(Empleado) +Quitar(Empleado)
+ObtenerSueldos():double +ObtenerSueldos():double Empleados
Empleado
-EsHoja()
-Empleados:Arraylist
+Agregar(Empleado)
+Quitar(Empleado) Empleados
+ObtenerSueldos():double
Daniel Mazzini
Daniel Mazzini
Patrones de Comportamiento
Propósito:
Asignación de responsabilidad = Distribuir el
comportamiento.
Comunicación entre instancias.
Se usa mas la composición que la herencia.
Cuales veremos?
Command
Strategy
State
Daniel Mazzini
Command
Problema:
Operaciones repetidas (por ejemplo, en el
menú y en el toolbar).
Necesita controlar la secuencia de las
operaciones.
Necesito hacer un log de las operaciones que
ejecuta el cliente.
Daniel Mazzini
Command
Cliente ICommand
+Hacer()
Comando1 Comando2
+Commando1(Estado) +Comando2(Ejecutar)
+Hacer() +Hacer()
Daniel Mazzini
Command
Tambien puedo:
Crear un método Deshacer en la Interfaz.
Puedo crear una pila de los últimos comandos
que se ejecutaran.
Puedo sacar de la pila de comandos
ejecutados y llamar al método Deshacer.
Juntándolo con el patrón Composite puedo
generar un comando Macro.
Daniel Mazzini
Command
Cliente Command
Manager
+Undo(int Cantidad)
+Redo(int Cantidad)
+CrearComando(estado)
ICommand
+Hacer() lista
+DesHacer()
Daniel Mazzini
State
Boya Estado
-EstadoActual:Estado +CambiarEstado()
Estado Estado
+CambiarEstado() +CambiarEstado()
Daniel Mazzini
Observer
Problema:
Mantener distintos objetos relacionados,
generalmente son relaciones 1 – N.
Mantener las dependencias entre objetos, sin
necesidad de conocer al otro objeto.
Tipos de objetos:
Publicador : Aquel que tiene que notificar de un
cambio.
Suscriptores: Aquellos interesados en recibir la
notificación.
Daniel Mazzini
Observer
Publicador Observador
+Agregar(Observador) +Actualizar()
+Quitar(Observador)
+Notificar()
Boya
+ObtenerEstado()
Daniel Mazzini
Otras consideraciones
Puedo enviar la información necesaria a
los suscriptores al notificar o que pida lo
que necesita (dependencia hacia el
publicador)
Ante casos de muchos publicadores,
puedo hacer un Gestor de Cambios que
haga la función de mediador.
Al notificar se puede usar delegados y
pasar clases que hereden de EventArgs al
Suscriptor.
Daniel Mazzini
Daniel Mazzini
Conclusiones
Empiece por un patron, estudie los
problemas que resuelve y pase cuando lo
haya probado.
Si la espada ya esta sobre su cabeza, lea
los problemas que resuelven todos los
patrones.
No deje de leer:
Patrones de Diseño, E. Gamma y otros (GoF).
Patterns of Enterprise Application
Architecture, Martin Fowler
Daniel Mazzini