Вы находитесь на странице: 1из 64

Patrones de Diseño

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.

Delegador Usa Delegado

+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

ListView Ordena «interface»


IComparer
+ListViewSorter : IComparer
+Comparer(in x : object, in y : object) : int
+Sort()

NumberComparer DateComparer

+Comparer(in x : object, in y : object) : int +Comparer(in x : object, in y : object) : int

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)

Clase base es abstracta.


«interface»
 Interfaz
+operacion1()
 La clase base puede +operacion2()

heredar de mas de una Abstracta


interfaz.
+operacion1()
 Una vez que están +operacion2()

escritos los métodos,


verifico si hay Concreta1 Concreta2 ...

duplicación en las clases +operacion1() +operacion1() +operacion1()

hijas. +operacion2() +operacion2() +operacion2()

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

Bicicleta Paris-Paris Moto Paris-Dakar

CuadroAluminio Rueda 26" CuadroAcero Rueda Moto

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

ParisDakar Ruedas CrearRueda() {


+CrearMovil(Chasis,Rueda[]):Movil return new RuedaMoto();
+CrearRueda():Rueda }
+CrearChasis():Chasis
+CrearTrazado():Trazado

GP de Catalunya Ruedas CrearRueda() {


+CrearMovil(Chasis,Rueda[]):Movil return new RuedaF1();
+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

Form Pedidos Cliente

Form Ctas Corrientes

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()

ExternoAdaptado ClaseA ClaseB


+ExternoAdaptado(Externa) +Operacion() +Operacion()
+Operacion()
_externa.DiferenteNombre()

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

ColorEsp TamañoEsp CompuestoAndEsp


+ColorEsp(ColorTipo) +TamañoEsp(TamañoTipo) +CompuestoEsp(Espec, Espec)
+EstaOK(Producto):bool +EstaOK(Producto):bool +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

ColorEsp TamañoEsp CompuestoEsp


#CompuestoEsp(Espec[])

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()

Comando1 Comando2 ComandoMacro


+Comando1(Estado) +Comando2(Estado) +Comando2(Estado)
+Hacer() +Hacer() +Hacer()
+Deshacer() +Deshacer() +Deshacer()
Daniel Mazzini
Daniel Mazzini
State
 Problema:
 Mantener el estado de un objeto.
 La organización de la lógica que maneja el
estado (maquina de estado) se torna
incontrolable.
 Acoplamiento entre la funcionalidad propia de
la clase y la funcionalidad para manejar el
estado de un objeto.

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()

foreach Observador item in al


{
Item.Actualizar() C.Control
+Actualizar()
}

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

Вам также может понравиться