Patrones de Diseño Daniel Mazzini [email protected] Ubica Solutions.
-
Upload
delfina-llamas -
Category
Documents
-
view
13 -
download
0
Transcript of Patrones de Diseño Daniel Mazzini [email protected] Ubica Solutions.
Patrones de DiseñoPatrones de Diseño
Daniel MazziniDaniel Mazzini
[email protected]@ubicasolutions.com
Ubica SolutionsUbica Solutions
Daniel MazziniDaniel Mazzini
Conocimientos previosConocimientos previos Conocimientos de POO.Conocimientos de POO. UML (básico)UML (básico) C#C#
Daniel MazziniDaniel Mazzini
AgendaAgenda
Propósito de los patronesPropósito de los patrones Fundamentos de diseño.Fundamentos de diseño.
•Creación.–Factory Method–Singleton–Abstract Factory
•Estructurales–Adapter–Facade–Composite
•Comportamiento–Command–State –Observer
Daniel MazziniDaniel Mazzini
Propósito de los patronesPropósito de los patrones ¿Qué es un patrón de diseño?¿Qué es un patrón de diseño? ¿Por qué usarlos?¿Por qué usarlos? CategorizaciónCategorización Problema - PatrónProblema - Patrón
Daniel MazziniDaniel Mazzini
¿Qué es un patrón de ¿Qué es un patrón de diseño?diseño?
Ante un problema reiterado ofrece una Ante un problema reiterado ofrece una solución contrastada que lo resuelve.solución contrastada que lo resuelve.
Describe el problema en forma sencilla.Describe el problema en forma sencilla. Describe el contexto en que ocurre.Describe el contexto en que ocurre. Describe los pasos a seguir.Describe los pasos a seguir. Describe los puntos fuertes y débiles de Describe los puntos fuertes y débiles de
la solución.la solución. Describe otros patrones asociados.Describe otros patrones asociados.
Daniel MazziniDaniel Mazzini
¿Por qué usarlos?¿Por qué usarlos?
Mejora en la comunicación y Mejora en la comunicación y documentacióndocumentación ““Hay que hacer un Factory Method”Hay que hacer un Factory Method” Facilita la documentación interna del proyecto.Facilita la documentación interna del proyecto.
Mejora la ingeniería de software.Mejora la ingeniería de software. Eleva el nivel del grupo de desarrollo.Eleva el nivel del grupo de desarrollo.
Previene “reinventar la rueda” en diseñoPreviene “reinventar la rueda” en diseño Son soluciones ya probadas.Son soluciones ya probadas.
Mejora la calidad y estructuraMejora la calidad y estructura ““¿Cuan grande debe ser una clase?”¿Cuan grande debe ser una clase?”
Daniel MazziniDaniel Mazzini
CategorizaciónCategorización FundamentalesFundamentales
Se usan en otros patrones mas grandesSe usan en otros patrones mas grandes CreaciónCreación
Aislar el proceso de creación de un Aislar el proceso de creación de un objeto.objeto.
EstructuraEstructura Desacopla el sistema.Desacopla el sistema.
ComportamientoComportamiento Describe situaciones de control de flujo.Describe situaciones de control de flujo.
Daniel MazziniDaniel Mazzini
Problema - PatrónProblema - Patrón Crear un objeto sin especificar la Crear un objeto sin especificar la
clase a la que pertenececlase a la que pertenece Abstract FactoryAbstract Factory Factory MethodFactory Method PrototypePrototype
Dependencia para tareas especificasDependencia para tareas especificas CommandCommand Cadena de ResponsabilidadCadena de Responsabilidad
Daniel MazziniDaniel Mazzini
Problema – Patrón (cont)Problema – Patrón (cont) Dependencia hacia el hardware o Dependencia hacia el hardware o
softwaresoftware Abstract FactoryAbstract Factory BridgeBridge
Dependencia hacia los algoritmosDependencia hacia los algoritmos StrategyStrategy Template MethodTemplate Method BuilderBuilder
Daniel MazziniDaniel Mazzini
Problema – Patrón (cont)Problema – Patrón (cont) Alto acoplamientoAlto acoplamiento
FaçadeFaçade MediatorMediator ObserverObserver
Imposibilidad de cambiar la clases Imposibilidad de cambiar la clases convenientementeconvenientemente AdapterAdapter DecoratorDecorator VisitorVisitor
Daniel MazziniDaniel Mazzini
Fundamentos de diseñoFundamentos de diseño
Programar para las interfaz, no para Programar para las interfaz, no para la herencia.la herencia.
Favorecer la composición antes que Favorecer la composición antes que la herencia.la herencia.
Delegación.Delegación. Doble Herencia.Doble Herencia.
Daniel MazziniDaniel Mazzini
Herencia o interfazHerencia o interfaz La herencia de clase define la La herencia de clase define la
implementación de una clase a partir implementación de una clase a partir de otra (excepto métodos abstractos)de otra (excepto métodos abstractos)
La herencia de interfaz define como se La herencia de interfaz define como se llamara el método o propiedad, llamara el método o propiedad, pudiendo escribir distinto código en pudiendo escribir distinto código en cada clase.cada clase.
Daniel MazziniDaniel Mazzini
Programar para las interfazProgramar para las interfaz Reutilizar la implementación de la Reutilizar la implementación de la
clase base es la mitad de la historia.clase base es la mitad de la historia. Ventajas:Ventajas:
Reducción de dependencias.Reducción de dependencias. El cliente desconoce la implementación.El cliente desconoce la implementación. La vinculación se realiza en tiempo de La vinculación se realiza en tiempo de
ejecución.ejecución. Da consistencia (contrato).Da consistencia (contrato).
Desventaja:Desventaja: Indireccionamiento.Indireccionamiento.
Daniel MazziniDaniel Mazzini
Favorecer la composiciónFavorecer la composición Ventajas de la herencia:Ventajas de la herencia:
Implementación ya realizada.Implementación ya realizada. Útil en situaciones “es un”Útil en situaciones “es un”
Desventajas de usar herencia:Desventajas de usar herencia: Construir un monstruo.Construir un monstruo. No se puede cambiar la implementación No se puede cambiar la implementación
heredada en tiempo de ejecución.heredada en tiempo de ejecución. Quebrar la encapsulación.Quebrar la encapsulación. Visibilidad. Visibilidad.
Daniel MazziniDaniel Mazzini
Favorecer la composición Favorecer la composición (cont)(cont)
Ventajas de la composición:Ventajas de la composición: Crear una nueva clase ensamblando con Crear una nueva clase ensamblando con
mas de una clase.mas de una clase. Puede cambiar la clase con la cual Puede cambiar la clase con la cual
ensamblo en tiempo de ejecución.ensamblo en tiempo de ejecución. Centrar cada clase en una tarea.Centrar cada clase en una tarea.
Desventaja de la composición:Desventaja de la composición: Requiere escribir un poco mas de Requiere escribir un poco mas de
código.código. Indireccionamiento.Indireccionamiento.
Daniel MazziniDaniel Mazzini
DelegaciónDelegación Una forma de componer.Una forma de componer. Se delega un conjunto de Se delega un conjunto de
operaciones de un objeto en otro operaciones de un objeto en otro objeto.objeto.
““La herencia” que use en VB6.La herencia” que use en VB6.
+operacion()
Delegador
+operacion()
Delegado
1 1
Usa
return Delegado.operacion()
Daniel MazziniDaniel Mazzini
Anti-EjemploAnti-Ejemplo
Ventana
+Area()
-Ancho : double-Alto : double
Rectangulo
return Ancho * Alto
Nuevo requerimiento:No todos las ventanas son cuadradas
Daniel MazziniDaniel Mazzini
Ejemplo de DelegadoEjemplo de Delegado
+Area() : double
«interface»ISuperficie
+Area() : double
-Ancho : double-Alto : double
Rectangulo
return Ancho * Alto;
+Area() : double
Ventanareturn ISuperficie.Area();
+Area() : double
-Radio : double
Circulo
return Pi * (Radio^2);
• Quito la herencia en ventana
• Creo una interfaz para comunicar el delegador con el delegado
• Creo un método llamado Area en Ventana (solo para mantener compatibilidad)
• Llamo al método de la interfaz que me da el área
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
Delegado en .NetDelegado en .Net
+Sort()
+ListViewSorter : IComparer
ListView
+Comparer(in x : object, in y : object) : int
«interface»IComparer
+Comparer(in x : object, in y : object) : int
NumberComparer
+Comparer(in x : object, in y : object) : int
DateComparer
Ordena
Daniel MazziniDaniel Mazzini
Doble HerenciaDoble Herencia Problema:Problema:
Mantener las clases que implementan Mantener las clases que implementan como internas del proyecto (internal o como internas del proyecto (internal o Friend), pero la interfaz pública.Friend), pero la interfaz pública.
Organizar clases que tienen un Organizar clases que tienen un comportamiento parecido para que sea comportamiento parecido para que sea consistente.consistente.
Daniel MazziniDaniel Mazzini
Doble Herencia (cont)Doble Herencia (cont)
Clase base es Clase base es abstracta.abstracta.
La clase base puede La clase base puede heredar de mas de heredar de mas de una interfaz.una interfaz.
Una vez que están Una vez que están escritos los métodos, escritos los métodos, verifico si hay verifico si hay duplicación en las duplicación en las clases hijas.clases hijas.
+operacion1()+operacion2()
Concreta1
+operacion1()+operacion2()
Abstracta
+operacion1()+operacion2()
«interface»Interfaz
+operacion1()+operacion2()
Concreta2
+operacion1()+operacion2()
...
Daniel MazziniDaniel Mazzini
Doble Herencia en .NETDoble Herencia en .NET
+Fill()+FillSchema()+...()
SQLDataAdapter
+Fill()+FillSchema()+...()
DataAdapter
+Fill()+FillSchema()+...()
«interface»IDataAdapter
+Fill()+FillSchema()+...()
OLEBDDataAdapter
Daniel MazziniDaniel Mazzini
Patrones de creaciónPatrones de creación
Propósito:Propósito: Crear un objeto es una toma de Crear un objeto es una toma de
decisión.decisión. Separar los procesos de creación de Separar los procesos de creación de
objeto y de uso de un objeto.objeto y de uso de un objeto. Cuales veremos?Cuales veremos?
Factory MethodFactory Method SingletonSingleton Abstract FactoryAbstract Factory
Daniel MazziniDaniel Mazzini
Factory MethodFactory Method Problema:Problema:
La instancia del objeto a crear depende La instancia del objeto a crear depende de condiciones externas a la clase de condiciones externas a la clase cliente.cliente.
Puede cambiar independientemente de Puede cambiar independientemente de cambiar la clase cliente.cambiar la clase cliente.
Ya he creado la estructura con “Doble Ya he creado la estructura con “Doble Herencia”, pero ahora necesito poder Herencia”, pero ahora necesito poder crear una instancia de cualquier clase crear una instancia de cualquier clase concreta.concreta.
Daniel MazziniDaniel Mazzini
+Fill()+FillSchema()+...()
SQLDataAdapter
+Fill()+FillSchema()+...()
DataAdapter
+Fill()+FillSchema()+...()
«interface»IDataAdapter
+Fill()+FillSchema()+...()
OLEBDDataAdapter
Cliente Editar
Factory MethodFactory Method
+CrearDataAdapter(in tipo : int) : IDataAdapter
«interface»IFactoriaDataAdapter
Crear
+CrearDataAdapter(in tipo : int) : IDataAdapter
FactoriaDataAdapter
Crear
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
F.M. con Constructor F.M. con Constructor EstáticoEstático
#MD5()
MD5
+Create(in tipo : string) : HashAlgorithm
HashAlgorithm
«interface»ICryptoTransform
Cliente Usar
Crear
#SHA1()
SHA1
#SHA256()
SHA256
•Método estático en clase abstracta que retorno instancias.• Constructores privados o protegidos.
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
SingletonSingleton Problema:Problema:
No se puede tener mas de una instancia No se puede tener mas de una instancia de una clase.de una clase.
Se necesita controlar el acceso a una Se necesita controlar el acceso a una clase.clase.
Daniel MazziniDaniel Mazzini
SingletonSingleton
if (instancia==null){ Mutex mutex = new Mutex(); mutex.WaitOne(); if(instancia==null) instancia = new ClaseUnica(); mutex.Close();}return instancia;
if (instancia==null) instancia = new ClaseUnica();return instancia;
-ClaseUnica()+ObtenerInstancia() : ClaseUnica+Operacion1()
-instancia : ClaseUnica
ClaseUnica• Cambio el constructor a privado.• Hago que la clase no pueda ser
heredada.• Agrego una variable estática del
mismo tipo de la clase donde esta contenida. (instancia)
• Agrego un método estático que retorne la variable estática. (GetInstance)
• No creo el objeto hasta que sea necesario (Lazy Creation)
• Agrego el código necesario para no crear dos instancias en distintos thread.
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
Abstract FactoryAbstract Factory ProblemaProblema
Necesito crear una familia de objetos.Necesito crear una familia de objetos. Trabajo con mas de una familia.Trabajo con mas de una familia. No puedo combinar ítems de las familias No puedo combinar ítems de las familias
de objetos.de objetos. El resto del sistema debe trabaja sin El resto del sistema debe trabaja sin
distinguir entre familias de objetos.distinguir entre familias de objetos.
Daniel MazziniDaniel Mazzini
TourDeFrancia
Abstract FactoryAbstract Factory
Bicicleta Paris-Paris
CuadroAluminio Rueda 26"
ParisDakar
GP de Catalunya
Moto Paris-Dakar
CuadroAcero Rueda Moto
Monoplaza Rueda F1
F1 Circuito Montmelo
Carrera
Movil Trazado
Chasis Rueda
Daniel MazziniDaniel Mazzini
Carrera+CrearMovil(Chasis,Rueda[]):Movil+CrearRueda():Rueda+CrearChasis():Chasis+CrearTrazado():Trazado
TourDeFrancia+CrearMovil(Chasis,Rueda[]):Movil+CrearRueda():Rueda+CrearChasis():Chasis+CrearTrazado():Trazado
Ruedas CrearRueda() { return new Rueda26();}
ParisDakar+CrearMovil(Chasis,Rueda[]):Movil+CrearRueda():Rueda+CrearChasis():Chasis+CrearTrazado():Trazado
Ruedas CrearRueda() { return new RuedaMoto();}
GP de Catalunya+CrearMovil(Chasis,Rueda[]):Movil+CrearRueda():Rueda+CrearChasis():Chasis+CrearTrazado():Trazado
Ruedas CrearRueda() { return new RuedaF1();}
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
Patrones de estructuraPatrones de estructura
Propósito:Propósito: Desacoplar el sistema.Desacoplar el sistema. Obtener una estructura flexible.Obtener una estructura flexible. Organizar.Organizar.
Cuales veremos?Cuales veremos? AdapterAdapter FacadeFacade CompositeComposite
Daniel MazziniDaniel Mazzini
FacadeFacade Problemas:Problemas:
El cliente hace muchos viajes al El cliente hace muchos viajes al servidor.servidor.
Separe por capas, pero tengo muchas Separe por capas, pero tengo muchas clases públicas en el servidor para que clases públicas en el servidor para que puedan ser creadas desde el cliente.puedan ser creadas desde el cliente.
Necesito estructurar las llamadas desde Necesito estructurar las llamadas desde el cliente.el cliente.
Daniel MazziniDaniel Mazzini
FacadeFacade
Form Cliente
Form Pedidos
Form Ctas Corrientes
Presentación Lógica
Cliente
Daniel MazziniDaniel Mazzini
FacadeFacadeCliente A B C
A.M
B.M
C.M
Facade A B CCliente
F.MA.M
B.M
C.M
Daniel MazziniDaniel Mazzini
FacadeFacade
Caso de Uso = FacadeCaso de Uso = Facade Un caso de uso es lo interacción de un Un caso de uso es lo interacción de un
actor con el sistema. La métodos de la actor con el sistema. La métodos de la fachada encapsulan los pasos fachada encapsulan los pasos necesarios para llevar a cabo lo que el necesarios para llevar a cabo lo que el cliente desea hacer.cliente desea hacer.
SistemaFacturacion
Cliente
Login
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
AdapterAdapter Problemas:Problemas:
Necesitamos llamar a un método a Necesitamos llamar a un método a través de una interfaz para no tener través de una interfaz para no tener dependencia en el cliente.dependencia en el cliente.
La librería a la que hay que llamar no es La librería a la que hay que llamar no es nuestra y no implementa esa interfaz.nuestra y no implementa esa interfaz.
No contamos con el código fuente de la No contamos con el código fuente de la librería.librería.
Daniel MazziniDaniel Mazzini
AdapterAdapter
Cliente IOperacion+Operacion()
Externa+DiferenteNombre()
ClaseA+Operacion()
ClaseB+Operacion()
ExternoAdaptado+ExternoAdaptado(Externa)+Operacion()
_externa.DiferenteNombre()
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
CompositeComposite Problema:Problema:
Estructuras de árbol o estructuras 1-N.Estructuras de árbol o estructuras 1-N. Tiene un objeto complejo que hay que Tiene un objeto complejo que hay que
descomponer en partes.descomponer en partes. Nodos especiales que pueden contener Nodos especiales que pueden contener
otros nodos.otros nodos.
Daniel MazziniDaniel Mazzini
CompositeComposite
Especificación+EstaOK(Producto):bool
Almacén-Productos():ArrayList+Seleccionar(Especificacion):ArrayList
ColorEsp+ColorEsp(ColorTipo)+EstaOK(Producto):bool
TamañoEsp+TamañoEsp(TamañoTipo)+EstaOK(Producto):bool
Espec Rojos = new ColorEsp(Color.Red);ArrayList prodRojos =alm.Seleccionar(Rojos);
Espec Peq = new TamañoEsp(Tamaño.Pequeño);ArrayList prodPeq = alm.Seleccionar(Peq);
Espec RojoPeq = new CompuestoAndEsp(
new ColorEsp(Color.Red),new TamañoEsp(Tamaño.Pequeño));
ArrayList prodRojos =alm.Seleccionar(RojoPeq);
return (_espec1.EstaOK(Producto) && _espec2.EstaOK(Producto));
CompuestoAndEsp+CompuestoEsp(Espec, Espec)+EstaOK(Producto):bool
Daniel MazziniDaniel Mazzini
CompositeComposite
Especificación+EstaOK(Producto):bool
Almacén-Productos():ArrayList+Seleccionar(Especificacion):ArrayList
ColorEsp TamañoEsp
Espec[] ar = new Espec[] {new ColorEsp(Color.Red),
new TamañoEsp(Tamaño.Pequeño)};Espec ExpresionOr = new CompOrEsp(ar);ArrayList prodRojos =alm.Seleccionar(ExpresionOr);
CompuestoEsp#CompuestoEsp(Espec[])
CompAndEsp+CompAndEsp(Espec[])+EstaOK(Producto):bool
CompOrEsp+CompOrEsp(Espec[])+EstaOK(Producto):bool
Lista
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
Composite DinámicoComposite DinámicoEmpleado
+Agregar(Empleado)+Quitar(Empleado)+ObtenerSueldos():double
NodosHojas NodosPadre+Agregar(Empleado)+Quitar(Empleado)+ObtenerSueldos():double Empleados
+Agregar(Empleado)+Quitar(Empleado)+ObtenerSueldos():double
Empleado
+Agregar(Empleado)+Quitar(Empleado)+ObtenerSueldos():double
-EsHoja()-Empleados:Arraylist
Empleados
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
Patrones de Patrones de ComportamientoComportamiento
Propósito:Propósito: Asignación de responsabilidad = Asignación de responsabilidad =
Distribuir el comportamiento.Distribuir el comportamiento. Comunicación entre instancias.Comunicación entre instancias. Se usa mas la composición que la Se usa mas la composición que la
herencia.herencia. Cuales veremos?Cuales veremos?
CommandCommand StrategyStrategy StateState
Daniel MazziniDaniel Mazzini
CommandCommand Problema:Problema:
Operaciones repetidas (por ejemplo, en Operaciones repetidas (por ejemplo, en el menú y en el toolbar).el menú y en el toolbar).
Necesita controlar la secuencia de las Necesita controlar la secuencia de las operaciones.operaciones.
Necesito hacer un log de las Necesito hacer un log de las operaciones que ejecuta el cliente.operaciones que ejecuta el cliente.
Daniel MazziniDaniel Mazzini
CommandCommand
ICommand+Hacer()
Comando1+Commando1(Estado)
+Hacer()
Comando2+Comando2(Ejecutar)
+Hacer()
Cliente
Daniel MazziniDaniel Mazzini
CommandCommand Tambien puedo:Tambien puedo:
Crear un método Deshacer en la Crear un método Deshacer en la Interfaz.Interfaz.
Puedo crear una pila de los últimos Puedo crear una pila de los últimos comandos que se ejecutaran.comandos que se ejecutaran.
Puedo sacar de la pila de comandos Puedo sacar de la pila de comandos ejecutados y llamar al método ejecutados y llamar al método Deshacer.Deshacer.
Juntándolo con el patrón Composite Juntándolo con el patrón Composite puedo generar un comando Macro.puedo generar un comando Macro.
Daniel MazziniDaniel Mazzini
CommandCommand
CommandManager
Cliente
+Undo(int Cantidad)+Redo(int Cantidad)+CrearComando(estado)
ICommand+Hacer()+DesHacer()
Comando1+Comando1(Estado)+Hacer()+Deshacer()
Comando2+Comando2(Estado)+Hacer()+Deshacer()
ComandoMacro+Comando2(Estado)+Hacer()+Deshacer()
lista
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
StateState Problema:Problema:
Mantener el estado de un objeto.Mantener el estado de un objeto. La organización de la lógica que maneja La organización de la lógica que maneja
el estado (maquina de estado) se torna el estado (maquina de estado) se torna incontrolable.incontrolable.
Acoplamiento entre la funcionalidad Acoplamiento entre la funcionalidad propia de la clase y la funcionalidad propia de la clase y la funcionalidad para manejar el estado de un objeto.para manejar el estado de un objeto.
Daniel MazziniDaniel Mazzini
StateState
Boya-EstadoActual:Estado
Estado+CambiarEstado()
Estado+CambiarEstado()
Estado+CambiarEstado()
Daniel MazziniDaniel Mazzini
ObserverObserver Problema:Problema:
Mantener distintos objetos relacionados, Mantener distintos objetos relacionados, generalmente son relaciones 1 – N.generalmente son relaciones 1 – N.
Mantener las dependencias entre objetos, sin Mantener las dependencias entre objetos, sin necesidad de conocer al otro objeto.necesidad de conocer al otro objeto.
Tipos de objetos:Tipos de objetos: Publicador : Aquel que tiene que notificar de un Publicador : Aquel que tiene que notificar de un
cambio.cambio. Suscriptores: Aquellos interesados en recibir la Suscriptores: Aquellos interesados en recibir la
notificación.notificación.
Daniel MazziniDaniel Mazzini
ObserverObserver
Publicador+Agregar(Observador)+Quitar(Observador)+Notificar()
Observador+Actualizar()
Boya+ObtenerEstado()
C.Control+Actualizar()
foreach Observador item in al{
Item.Actualizar()}
Daniel MazziniDaniel Mazzini
Otras consideracionesOtras consideraciones Puedo enviar la información Puedo enviar la información
necesaria a los suscriptores al necesaria a los suscriptores al notificar o que pida lo que necesita notificar o que pida lo que necesita (dependencia hacia el publicador)(dependencia hacia el publicador)
Ante casos de muchos publicadores, Ante casos de muchos publicadores, puedo hacer un Gestor de Cambios puedo hacer un Gestor de Cambios que haga la función de mediador.que haga la función de mediador.
Al notificar se puede usar delegados Al notificar se puede usar delegados y pasar clases que hereden de y pasar clases que hereden de EventArgs al Suscriptor.EventArgs al Suscriptor.
Daniel MazziniDaniel Mazzini
Daniel MazziniDaniel Mazzini
ConclusionesConclusiones Empiece por un patron, estudie los Empiece por un patron, estudie los
problemas que resuelve y pase problemas que resuelve y pase cuando lo haya probado.cuando lo haya probado.
Si la espada ya esta sobre su cabeza, Si la espada ya esta sobre su cabeza, lea los problemas que resuelven todos lea los problemas que resuelven todos los patrones.los patrones.
No deje de leer:No deje de leer: Patrones de Diseño, E. Gamma y otros Patrones de Diseño, E. Gamma y otros
(GoF).(GoF). Patterns of Enterprise Application Patterns of Enterprise Application
Architecture, Martin FowlerArchitecture, Martin Fowler