Patrones GoF ANALISIS Y DISEÑ DISEÑO O.O. Patrones GoF GoF (gang of four) 23 patrones presentados por la “pandilla de los cuatro” en el libro “Design Patterns”. Gamma, Helm, Johnson, Vlissides. 1995. 1 Patrones GoF ¿Cómo usar un patró patrón de diseñ diseño? Conocer en gran parte la solució solución gené genérica que brinda cada patró patrón y el tipo de problemá problemática que resuelven Evaluar la posibilidad de aplicar el o los patrones en el problema correspondiente Definir la implementació implementación de los mismos en nuestro modelo. Nombre de clases, métodos y atributos Implementar los mé métodos correspondientes Patrones GoF De creació creación: Forma de crear instancias. Abstraer y ocultar có cómo son creados e inicializados los objetos (Factorí ), Singleton) (Factoría (Factory (Factory), Singleton) Estructurales: Cómo se combinan clases y objetos para formar nuevas estructuras y proporcionar nuevas funciones (Adaptador (Adapter )) (Adapter)) De comportamiento: Ayudan a definir la comunicació comunicación e interacció interacción de los objetos. Reducir acoplamiento (Observer). Observer). 2 Patrones G o F Patrones de Creación Abstract Factory Factory Method Singleton Patrones Estructurales Composite Adapter Patrones de Comportamiento Observer Patrones De creación Separan la forma en que se crean los objetos, para tratar las clases a crear de forma genérica. Se ocultan los métodos y clases concretas de tal forma que al variar su implementación no se vea afectado el resto de la aplicación. 3 Factoria (Factory) Su propósito es definir una interface para crear objetos donde se delega la creación de las instancias a las subclases. La clase factoría devuelve una instancia de un objeto según los datos que se le pasan como parámetros. Se encarga de centralizar el sitio donde se crean los objetos, normalmente donde se crean objetos de una misma "familia“. Factoria (Factory) Motivación: Un sistema debe ser independiente de cómo se crean, componen y representan sus productos Un sistema debe ser configurado con una familia de productos Una familia de objetos relacionados está diseñada para ser usada conjuntamente, y es necesario hacer cumplir esta restricción. Quiere proporcionar una biblioteca de clases, y sólo quiere revelar sus interfaces, no sus implementaciones. 4 Factoria (Factory) Una clase C cliente de una clase abstracta A necesita crear instancias de subclases de A que no conoce Clase A <<abstract>> Documento <<abstract>> Aplicacion setDoc open() close() save() revert() crearDocumento() nuevoDocumento() openDocumento() Documento d d = crearDocumento(); setDoc.add(d); d.open() “método factoria” MiAplicacion MiDocumento crearDocumento() Clase C return new MiDocumento Ejemplo del patrón Factory Method Factoria (Factory) Aplicabilidad Una clase no puede anticipar la clase de objetos que debe crear. Una clase desea que sus subclases especifiquen los objetos que debe crear. <<abstract>> Manipulador <<abstract>> Figura Cliente downClick() drag() upClick() crearManipulador() Linea crearManipulador() Circulo ManipuladorLinea ManipuladorCirculo crearManipulador() Ejemplo del patrón Abstract Factory 5 Factoria (Factory) Implementación Dos posibilidades Creador es una clase abstracta con un método factorí factoría abstracto. Creador es una clase concreta que ofrece una implementació implementación por defecto del mé método factorí factoría. El mé método factorí factoría puede tener un pará parámetro que identifica a la clase del objeto a crear. Factoria (Factory) Programa public abstract Figura { int lado = 0; public Figura (int lado) { this.lado = lado; } public abstract int getArea (); public abstract void dibujar (Graphics g, int x, int y); } 6 Factoria (Factory) public Circulo { public Circulo (int lado) { super (lado); } public int getArea () { return (Math.PI x lado x lado); } public void dibujar (Graphics g, int x, int y) { g.setColor (Color.black); g.setDrawArc (x, y, lado, lado, 0, 360); } } public Cuadrado { public Cuadrado (int lado) { super (lado); } public int getArea () { return (lado x lado); } public void dibujar (Graphics g, int x, int y) { g.setColor (Color.black); g.setDrawRect (x, y, lado, lado); } } Factoria (Factory) public void FactoriaDeFiguras { public static final int CUADRADO = 0 public static final int CIRCULO = 1 public Figura getFigura (int tipo, int lado) { if (tipo == this.CUADRADO) { return (new Cuadrado (lado)) } else { return (new Circulo (lado)) } } } 7 Factoria (Factory) Ventajas: Aisla las clases concretas para el cliente Facilita el intercambio entre familias de clase Promueve la consistencia Desventajas: No es sencillo agregar elementos a la factorí factoría. Requiere modificar la interface Requiere modificar las subclases Patrones GoF Abstract Factory Este patrón proporciona una interface para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. 8 Abstract Factory Se utiliza cuando… cuando… Un sistema deberí debería ser independiente de cómo sus productos son creados, compuestos o representados. Un sistema serí sería configurado con uno de sus mú múltiples familias de productos. Se necesita proveer una librerí librería de clases de productos y se desea mostrar sus interfaces, no sus implementaciones. Se necesita que un conjunto de productos relacionados sean utilizados juntos. Abstract Factory La estructura tí típica es: Abstract Factory: Definició de Factory: Definición interfaces para la familia de productos gené genéricos Concrete Factory: Factory: Implementació Implementación de las interfaces de los productos para cada una de las familias concretas Abstract Product: Product: Definició Definición de los métodos de creació creación gené genéricos en la interface de la fá fábrica. (retornan las interfaces gené genéricas) Concrete Product: Product: Implementació Implementación de una fá fábrica para cada una de las familias concretas. 9 Abstract Factory Estructura tí típica Abstract Factory Abstract Product Concrete Product Concrete Factory Abstract Factory Ventajas y Desventajas Aisla las Clases concretas: El cliente manipula instancias a travé través de las interfaces abstractas. Facilita el intercambio de familias de productos: Se puede cambiar la configuració ó n de un producto simplemente configuraci cambiando la factoria concreta. Promueve la consistencia entre productos: Cuando los objetos de una familia trabajan juntos, la aplicació aplicación que los usa debe utilizar la misma familia Es difí difícil manejar nuevas clases de productos: Implica cambios en la clase Abstract Factory. Factory. 10 Patrones GoF Factory Method Define una interface para crear un objeto, pero deja a las subclases decidir qué clase instanciar. Se usa cuando: Una clase no puede anticipar la clase de objetos que debe crear. Una clase quiere que sus subclases especifiquen las clases que ella debe crear. Factory Method Utiliza una clase constructora (al estilo del Abstract Factory) Factory) abstracta con unos cuantos mé métodos definidos y otro(s) otro(s) abstracto(s): abstracto(s): el dedicado a la construcció construcción de objetos de un subtipo de un tipo determinado. Las clases principales en este patró patrón son el creador y el producto. 11 Factory Method El creador necesita crear instancias de productos, pero el tipo concreto de producto no debe ser forzado en las subclases del creador, porque entonces las posibles subclases del creador deben poder especificar subclases del producto para utilizar. Factory Method Clase A <<abstract>> Documento setDoc open() close() save() revert() <<abstract>> Aplicacion crearDocumento() nuevoDocumento() openDocumento() Documento d d = crearDocumento(); setDoc.add(d); d.open() “método factoria” MiAplicacion MiDocumento crearDocumento() Clase C return new MiDocumento Ejemplo del patrón Factory Method 12 Factory Method Una desventaja es tener que crear una subclase de la clase Creator sólo para crear un objeto de la clase ConcreteProduct Creator Product FactoryMethod() … Product=FactoryMethod() … AnOperation() ConcreteCreator FactoryMethod() ConcretProduct return new ConcreteProduct AnOperation() Factory Method // Definimos la clase abstracta Creator public abstract class Creator{ Creator{ // Operació Operación que realiza public void anOperation() anOperation(){{ Product aProduct = factoryMethod() factoryMethod();; } // Definimos mé método abstracto protected abstract Product factoryMethod() factoryMethod();; } 13 Factory Method //Ahora definimos el creador concreto. public class ConcreteCreator extends Creator{ Creator{ protected Product factoryMethod() factoryMethod() { return new ConcreteProduct() ConcreteProduct();; } } //Y definimos el producto y su implementació implementación concreta. public interface Product{ Product{ String hacer(); } public class ConcreteProduct implements Product{ Product{ … } Factory Method //Y un ejemplo de uso : public static void main(String main(String args[]){ args[]){ Creator aCreator; aCreator; aCreator = new ConcreteCreator(); ConcreteCreator(); aCreator.anOperation(); aCreator.anOperation(); } 14 Patrones GoF Singleton Asegura que sólo se cree una instancia de la clase y provee un punto global de acceso a ésta. Este patrón es útil cuando se quiere tener solamente un objeto único instanciado (Ej: Cola de impresión, Conexión a BD, etc). Singleton Cuenta con un método o propiedad compartida (shared) que se encarga de regresar la clase instanciada. El constructor de la clase debe ser privado para evitar que se creen instancias de la clase. Dentro de la clase tendremos nuestra instancia viva. 15 Singleton Singleton unicaInstancia datoSingleton return unicaInstancia instancia() operacionSingleton() getSingleton() Singleton final class Coche { /* la única instancia de coche que se permitirá. No es obligatorio crear el Singleton estáticamente, se podría proveer un método que lo cree */ private static Coche c = new Coche(); // atributos private Motor motor = new Motor(); ... //constructor privado para que no se pueda instanciar private Coche(){} //vacío porque creamos la instancia estáticamente // método que devuelve el "singleton" Coche public static Coche getCoche () { return c; } // resto de métodos public void acelerar() { // implementación del metodo } 16 Singleton class ClaseSingletonEjemplo { static ClaseSingletonEjemplo unicaInstancia; public static ClaseSingletonEjemplo Instance(){ if (unicaInstancia == null) unicaInstancia = new ClaseSingletonEjemplo(); return unicaInstancia; } private ClaseSingletonEjemplo(){} }; Patrones GoF Composite Compone objetos en estructuras arborescentes para representar jerarquí jerarquías TODOTODO-Partes Permite manejar indistintamente objetos individuales y composiciones de objetos 17 Composite Cliente Componente Operación() Adicionar(Componente) Remover(Componente) obtenerHijo(int) Hoja Operación() Composite Operación() hijos Adicionar(Componente) Remover(Componente) obtenerHijo(int) Para todo g en hijos: g.Operación() Composite La estructura tí típica es: Componente Hoja Declara la interface para objetos en la composició composición y se encarga de acceder y manejar sus componentes hijo Representa objetos hoja (sin hijos) en la composició composición y define un comportamiento especí específico Composite Almacena componentes hijo y define un comportamiento (adicionar, eliminar, modificar… modificar…) para sus componentes hijos 18 Composite Componente ObjetoGráfico Dibujar() Adicionar(ObjetoGráfico) Remover(ObjetoGráfico) obtenerHijo(int) Composite Hoja Hoja Hoja Línea Texto Rectángulo Dibujar() Dibujar() Dibujar() En Dibujar() de figura: para todo g en el contenedor elementos g.Dibujar() elementos Figura Dibujar() Adicionar(ObjetoGráfico g) Remover(ObjetoGráfico g) obtenerHijo(int) Adicionar o remover g del contenedor elementos Patrones GoF Adapter Convierte la interface de una clase en otra interface que el cliente espera Permite a las clases trabajar juntas ya que de otra manera no lo podrí podrían hacer debido a que las interfaces son incompatibles. 19 Adaptador (Adapter/Wrapper) Se asegura de convertir la interface de una clase en otra que el cliente espera. Permite la colaboración de ciertas clases a pesar de tener interfaces incompatibles Se desea crear una clase reutilizable que debe colaborar con clases no relacionadas o imprevistas. La funcionalidad de Adaptador depende de la similitud entre la interfaz de las clases Objetivo y Adaptado. Adaptador Objetivo Colabora con los objetos conforman la interface Objetivo que Adaptado dominio Cliente Define la interface de especí específico que el cliente usa Define una interface existente que necesita adaptarse Adaptador Adapta la interface Adaptado a la interface Objetivo 20 Adaptador (Adapter/Wrapper) Estructura 1: Herencia Múltiple Interface que el cliente espera Interface existente que se requiere adaptar Adapta la interface “Adaptee” al “Target esperado usando herencia múltiple Adaptador (Adapter/Wrapper) Estructura 2: Objeto Adaptador Interface que el cliente espera Interface existente que se requiere adaptar Adapta la interface “Adaptee” al “Target esperado usando un objeto adaptador 21 Adaptador Cliente Objetivo Adaptado RequerimientoEspecífico() Requerimiento() implementación Adaptador Requerimiento() Realmente se invoca el RequerimientoEspecífico() Adaptador (Adapter/Wrapper) Cliente ElementoGrafico Objetivo Editor marco() crearManipulador() Adaptador ElemLinea marco() crearManipulador() return text.getExtension ElemTexto marco() crearManipulador() return new ManipuladorTexto +texto Adaptado TextView getExtension() 22 Adaptador (Adapter/Wrapper) Objetivo, Cliente TreeDisplay getChildren(Node) CreateGraphicNode(Node) display() BuildTree(Node n) Abstracta getChildren(n); for each child { addGraphicNode(CreateGraphicNode(child)); buildTree(child) } DirectoryTreeDisplay FileSystemEntity getChildren(Node) createGraphicNode(Node) adaptador adaptado Patrones GoF Observer Define una dependencia de uno a muchos entre objetos así así que cuando un objeto cambia de estado, todos los objetos que dependen de él son notificados para que se actualicen automá automáticamente. 23 Patrones GoF Observer Define una dependencia de uno a muchos objetos de tal manera que cuando un objeto cambia su estado, todas sus dependencias son notificadas actualizándose de manera automática Se usa cuando una abstracción tiene dos aspectos y uno depende del otro. Encapsular estos dos aspectos en objetos separados permite actualizarlos y reutilizarlos de manera independiente. Cuando un cambio en un objeto requiere cambios en otros objetos asociados sin importar el tipo de esos cambios! Observer Sus son: principales componentes Sujeto: Puede tener asociados uno o má más observadores Observador: Es notificado cuando el sujeto cambia de estado. Cada observador pregunta al sujeto acerca de su estado con el fin de sincronizar su estado con el del sujeto. 24 Observer Observadores: N Observadores que cambian su presentación dependiendo de los datos del “Sujeto” a b c x 60 30 10 y 50 30 20 x x 80 60 40 a x b 20 c 0 a z 80 10 b c 10 Ejemplo: Uso de una interfaz gráfica para separar la presentación de la lógica de los datos Promedio a = 60 b = 30 c = 10 Todos los Observadores son notificados de cualquier cambio en el estado del “Sujeto” Notificación de Sujeto cambio Solicitudes, modificaciones Observer Define una inteface actualizable para objetos que podrían ser notificados de cambios en el “Sujeto” Conoce a todos sus Observadores Sujeto Asociar (Observador) Desasociar (Observador) Notificar() Mantiene un estado y nofitica a los Observadores de sus cambios SujetoConcreto estadoSujeto darEstado() modificarEstado() darEstado() retorna estadoSujeto Observador observadores Actualizar() Para todo o en observadores: o.Actualizar() Implementa la Interface para mantener la actualización acorde con el estado del “Sujeto” ObservadorConcreto sujeto estadoObservador Actualizar() estadoObservador= sujeto.darEstado() 25 Observer Ejemplo de Implementación utilizando un Manejador del Cambio: (evita al sujeto tener las referencias de sus observadores) 26