07Patrones

Reutilización del Software

Patrones de Diseño

1

Introducción
• El diseño OO es difícil y el diseño de software orientado a objetos reutilizable lo es aún más. • Los diseñadores expertos no resuelven los problemas desde sus principios; reutilizan soluciones que han funcionado en el pasado.
– Se encuentran patrones de clases y objetos de comunicación recurrentes en muchos sistemas orientados a objetos. – Estos patrones resuelven problemas de diseño específicos y hacen el diseño flexible y reusable.
2

Definición de un patrón
Alexander(arquitecto/urbanista)

Cada patrón describe un problema que ocurre una y otra vez en nuestro entorno y describe también el núcleo de la solución al problema, de forma que puede utilizarse un millón de veces sin tener que hacer dos veces lo mismo.

3

Definición de un patrón de diseño [Gamma] Un patrón de diseño es una descripción de clases y objetos comunicándose entre sí adaptada para resolver un problema de diseño general en un contexto particular. 4 .

creando un cuerpo literario de base – Crea un lenguaje común para comunicar ideas y experiencia acerca de los problemas y sus soluciones • El uso de patrones ayuda a obtener un software de calidad (reutilización y extensibilidad) 5 .Introducción • Es un tema importante en el desarrollo de software actual: permite capturar la experiencia • Busca ayudar a la comunidad de desarrolladores de software a resolver problemas comunes.

• La solución: describe los elementos que componen el diseño. • El problema: describe cuándo aplicar el patrón.Elementos de un patrón • Nombre: describe el problema de diseño. responsabilidades y colaboración. 6 . sus relaciones.

Design Patterns. Vlissides. Helm. Gamma.net/patterns/ • Thinking in patterns with java http://www.. and J. R. Addison Wesley.net/Books/TIPatterns/ 7 . E. • Desing Patterns. 1995.. • Patterns Home Page: http://hillside. R. Johnson.Más información en.mindview.

– De estructura: tratan la composición de clases y/o objetos. – De comportamiento: caracterizan las formas en las que interactúan y reparten responsabilidades las distintas clases u objetos.Clasificación de los patrones • Según su propósito: – De creación: conciernen al proceso de creación de objetos. 8 .

Clasificación de los patrones GoF (gang of Four) [Gamma] Propósito Ámbito Clase Factory Method Adapter Adapter Abstract Factory Bridge Composite Decorator Facade Flyweight Proxy Interpreter Template Method Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor 9 Creación Estructural Comportamiento Objeto Builder Prototype Singleton Además: Patrón Delegation .

Patrón DELEGATION Utilidad: Cuando se quiere extender y reutilizar la funcionalidad de una clase SIN UTILIZAR LA HERENCIA Ventajas: • En vez de herencia múltiple • Cuando una clase que hereda de otra quiere ocultar algunos de los métodos heredados • Compartir código que NO se puede heredar 10 .

b2() …. Clase C a1(). .La clase C no desea TODOS los métodos de B 11 . Clase B b1().El lenguaje utilizado NO PERMITE HERENCIA MÚLTIPLE .Patrón DELEGATION El problema Clase A a1() …. b2() …. b1().

Clase B b1(). usa Clase C a1(). El método b1() habrá que añadirlo a C NO USAR HERENCIA SINO LA RELACIÓN “USA” 12 . b1() …. b2() ….Patrón DELEGATION La solución Clase A a1() ….

de B objB=new B().Patrón DELEGATION Implementación class C extends A { B objB.} ….b1( ). } void b1( ) { objB. C ( ) { // En la constructora se puede crear obj. 13 .

Clasificación de los patrones GoF (gang of Four) [Gamma] Propósito Ámbito Clase Factory Method Adapter Adapter Abstract Factory Bridge Composite Decorator Facade Flyweight Proxy Interpreter Template Method Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor 14 Creación Estructural Comportamiento Objeto Builder Prototype Singleton .

Patrón SINGLETON • Utilidad – Asegurar que una clase tiene una sola instancia y proporcionar un punto de acceso global a ella • Ventajas – Es necesario cuando hay clases que tienen que gestionar de manera centralizada un recurso – Una variable global no garantiza que sólo se instancie una vez 15 .

CSingleton () + getInstance () Atributos Método static .Patrón SINGLETON La solución – El constructor de la clase DEBE SER PRIVADO – Se proporciona un método ESTÁTICO en la clase que devuelve LA ÚNICA INSTANCIA DE LA CLASE: getInstance() Clase CSingleton .CSingleton laInstancia ….indica que es private Métodos + indica que es public 16 . .

Patrón SINGLETON Implementación public class CSingleton { private static CSingleton laInstancia = new CSingleton(). } …………………………. private CSingleton() {} public static CSingleton getInstance() { return laInstancia. } 17 .

Patrón SINGLETON Inconvenientes Se podría obtener una nueva instancia usando el esquema anterior: public class MiCSingleton extends CSingleton implements Cloneable {} MiCSingleton mcs = new MiCSingleton().} 18 . MiCSingleton mcsCopia = mcs..clone(). Para solucionarlo: definir CSingleton como final public final class CSingleton {..

addElement(p).} public Vector obtListaProfesores() {return listaProfesores. // y se guarda en laFacultad listaAsigs = new Vector(). SINGLETON private Vector listaMatrs.public final class Facultad implements Serializable { private Vector listaProfesores. EJEMPLO DE private Vector listaEstudiantes. private static Facultad laFacultad=new Facultad(). listaMatrs = new Vector().} public void anadirProfesor(Profesor p) {listaProfesores. private Facultad() // EL CONSTRUCTOR ES PRIVADO { listaProfesores = new Vector(). } public static Facultad getInstance() {return laFacultad. } 19 . PATRÓN private Vector listaAsigs. // Sólo hay UNA instancia listaEstudiantes= new Vector().

Clasificación de los patrones GoF (gang of Four) [Gamma] Propósito Ámbito Clase Factory Method Adapter Adapter Abstract Factory Bridge Composite Decorator Facade Flyweight Proxy Interpreter Template Method Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor 20 Creación Estructural Comportamiento Objeto Builder Prototype Singleton .

Permite que clases con interfaces incompatibles se comuniquen Ventajas Se quiere utilizar una clase ya existente y su interfaz no se corresponde con la interfaz que se necesita Se quiere envolver código no orientado a objeto con forma de clase 21 .Patrón ADAPTER Intención Convertir la interfaz de una clase en otra interfaz esperada por los clientes.

) …. Se desea utilizar la clase A (el método ejec) utilizando como entrada un objeto de la clase B objetoDeA.ejec(objetoDeB) Pero no se puede. .) m2(….Patrón ADAPTER El problema Clase A ejec(Interfaz C) Interfaz C m1(…. ya que la clase B no implementa la interfaz C 22 usa Clase B b1(….) ….) b2(….

Interfaz C usa m1(…. Al implementarla.) m2(….) ….) m2(…. Solución: construir una clase Adaptadora de B que implemente la interfaz C.Patrón ADAPTER La solución Clase A ejec(Interfaz C) Clase B b1(….) …. Clase AdapterB AdapterB(B) m1(….ejec(objetoDeAdapterB) usa .) …. usa un objeto de B y sus métodos Para utilizar la clase A: objetoDeAdapterB =NEW AdapterB(objetoDeB) 23 objetoDeA.) b2(….

...) b1() m2(. Para ello necesita crear un objeto adaptador que encapsule b b:B 24 .) b2() El cliente quiere usar el objeto a (para que ejecute el método ejec) con un objeto de b.Patrón ADAPTER Diagrama de interacción : Cliente ab: AdapterB a:A new AdapterB(b) ab ejec(ab) m1(..

m2().b2()…) los convierte/adapta a los métodos esperados por la clase A (métodos m1().…) 25 .Patrón ADAPTER • Convierte la interfaz de una clase en otra interfaz que los clientes esperan. Permite que clases con interfaces incompatibles puedan ser utilizadas conjuntamente. – La interfaz de la clase B (los métodos b1().

clear. 2. De JGL usa De Java usa Interfaz Sequence add. . size. put. isEmpty. 26 . Sorting. isEmpty. Clase IntArray IntArray(int [] ) Implementa: add. clear. Adapter proporcionado por JGL OBJETIVO: PODER USAR LOS ALGORITMOS DE JGL CON int [] int ints[] = { 3.Patrón ADAPTER Ejemplo de uso en JGL Clase Sorting sort(Sequence) Array Java nativo: int[] Operaciones con arrays: acceso elº i: int[i]. contains. size.... .. 4 }.. IntArray intArray = new IntArray( ints ).sort( intArray ). -3. (de Container) at. -1.

f().Patrón ADAPTER Ejemplo I class WhatIUse { public void op(WhatIWant wiw) { wiw. } class Adapter implements WhatIWant { WhatIHave whatIHave. } } .h(). public Adapter(WhatIHave wih) { whatIHave = wih.} } class WhatIHave { public void g() {} public void h() {} } interface WhatIWant { void f(). 27 whatIHave. } public void f() { // Implementa usando los // métodos de WhatIHave: whatIHave.g().

Patrón ADAPTER Ejemplo II ♦Extender un editor gráfico con clases de otro toolkit Gráfico Dibujar( ) Mover( ) Label Draw( ) Move( ) Polígono Dibujar( ) Mover( ) Cuadrado Dibujar( ) Mover( ) Círculo Dibujar( ) Mover( ) Texto Dibujar( ) Mover( ) 28 .

que sólo usan una interfaz ♦Facilita añadir nuevos componentes sin afectar a los clientes Inconvenientes ♦Es difícil restringir los tipos de los hijos ♦Las operaciones de gestión de hijos en los objetos simples pueden presentar problemas: seguridad frente a flexibilidad 29 .Patrón COMPOSITE Intención Componer objetos en jerarquías todo-parte y permitir a los clientes tratar objetos simples y compuestos de manera uniforme Ventajas ♦Permite tratamiento uniforme de objetos simples y complejos así como composiciones recursivas ♦Simplifica el código de los clientes.

Los marcos pueden contener columnas. 30 Marco Imagen . Las columnas y páginas pueden contener marcos. formadas por caracteres.Patrón COMPOSITE El problema: La escalabilidad Documento Página Columna LíneaDeTexto Carácter Un documento está formado por varias páginas. marcos y líneas de texto pueden contener imágenes. Las columnas. las cuales están formadas por columnas que contienen líneas de texto.

Los marcos pueden contener columnas. formadas por caracteres.Patrón COMPOSITE La solución 0. 31 . las cuales están formadas por columnas que contienen líneas de texto. Las columnas.. marcos y líneas de texto pueden contener imágenes. Las columnas y páginas pueden contener marcos.n ElementoDeDocumento Carácter Imagen ElemDeDocCompuesto Documento Página Columna Marco LíneaDeTexto Un documento está formado por varias páginas.

Patrón COMPOSITE La solución Cliente Componente Operación() m_hijo unCompuesto unCompuesto unSimple unSimple Simple Operación() Compuesto Operación() Add(c : Componente) Remove(c : Componente) Iterar() : Componente unSimple unSimple unCompuesto unCompuesto para cada hijo en m_hijo hijo->Operación(). ♦Simple: representa los objetos de la composición que no tienen hijos e implementa sus operaciones ♦Compuesto: implementa las operaciones para los componentes con hijos y almacena a los hijos ♦Cliente: utiliza objetos de la composición mediante la interfaz de Componente 32 . unSimple unSimple unSimple unSimple unSimple unSimple ♦Participantes ♦Componente: declara una clase abstracta para la composición de objetos.

Patrón COMPOSITE Ejemplo: La jerarquía de clases de AWT • Sirve para diseñar clases que agrupen a objetos complejos. los cuales a su vez están formados por objetos complejos y/o simples • La jerarquía de clases AWT se ha diseñado según el patrón COMPOSITE 33 .

1 panel que contenga 5 casillas de validación y una lista desplegable. 3 botones. 2 campos de texto y un botón -… Además. añadir nuevos tipos de contenedores y de componentes no sería muy 34 costoso (estaríamos ante una solución extensible) .Una ventana formada por 2 cajas de texto. 2 campos de texto. -Una ventana formada por 2 etiquetas.Patrón COMPOSITE Ejemplo: La jerarquía de clases de AWT COMPONENTE Applet CONTENEDOR (todo contenedor es un componente) Las posibilidades son infinitas… .

Dialog. addTextField.Se necesitarían métodos addButton. … .Patrón COMPOSITE Un diseño francamente malo … Button CheckBox TextField * Frame * * * … .Si se quisiera añadir un nuevo componente XXX. addFrame en la clase Frame (y los correspondientes a todos los que faltan) . habría que cambiar la 35 clase Frame y añadir el método addXXX (nada extensible) . addCheckBox. ya que un Button puede ser componente de un Panel.Además el diagrama está muy incompleto.

Componentes principales de Swing Applet JWindow JDialog JApplet JComponent JFrame JPanel JList JComboBox JMenuBar JTextField. JTextArea. JButton… 36 .

Clasificación de los patrones GoF (gang of Four) [Gamma] Propósito Ámbito Clase Factory Method Adapter Adapter Abstract Factory Bridge Composite Decorator Facade Flyweight Proxy Interpreter Template Method Chain of Responsability Command Iterator Mediator Memento Observer State Strategy Visitor 37 Creación Estructural Comportamiento Objeto Builder Prototype Singleton .

separar los objetos de presentación (vistas) de los objetos de datos. los n objetos sean notificados y se actualicen automáticamente • Motivación – En un toolkit de GUI.Patrón OBSERVER • Intención – Definir una dependencia 1:n de forma que cuando el objeto 1 cambie su estado. de forma que se puedan tener varias vistas sincronizadas de los mismos datos (editor-subscriptor) 38 .

Patrón OBSERVER Ejemplo observadores notificación de cambio peticiones. modificaciones a = 50% b = 30% c = 20% sujeto 39 .

. update() { // Qué hacer cuando // cambie el “objeto // observado” suSubject // Llamará: suSubject.... Clase ObsConcreta suSubject 1 Se implementa añadiendo el atributo Observable suSubject en ObsConcreta Class ObsConcreto set(.Patrón OBSERVER La solución Clase OBSERVADA (Modelo) Se implementa añadiendo el atributo Vector susObservers en Subject Class Observable addObserver(Observer) removeObserver(Observer) notifyObservers() setChanged() susObservers Clases OBSERVADORAS (Vistas) Interfaz Observer 0....get() 40 } ...){ // call notifyObservers()} get() {....} .* update() ….

Patrón OBSERVER Diagrama de interacción s: Observable set(....) Se cambia algún valor de s oi: Observer addObserver(oi) Registrarse como “observador” de s setChanged() notityObservers() update() get(.) Llama a update() para cada objeto de susObservers “actualizarse con los nuevos valores” de s 41 ..

Patrón OBSERVER La clase Observable Métodos addObserver (o) deleteObserver(o) deleteObservers countObservers setChanged() hasChanged notifyObservers Significado Añade un nuevo observador o Elimina el observador o Elimina todos los observadores Devuelve el número de observadores marca el objeto como “modificado” Devuelve cierto si el objeto esta “modificado” Notifica a todos los objetos suscritos si el objeto esta en Estado “modificado” La interfaz Observer update() Este método es invocado cuando el objeto observado ha cambiado 42 .

edu/~bergin/mvc/mvcgui.pace.Patrón OBSERVER Otro Ejemplo http://csis.html Building Graphical User Interfaces with the MVC Pattern 43 .

util.0. setChanged(). } private double temperatureF = 32.Observable{ public double getF(){return temperatureF. public class Observado extends java.} public double getC(){return (temperatureF .0 + 32.0) * 5.*. notifyObservers().util.0 / 9. setChanged().0.Patrón OBSERVER Ejemplo: La clase Observable (el modelo) package mvc. } 44 .0.} public void setF(double tempF){ temperatureF = tempF. notifyObservers().32.0/5. } public void setC(double tempC){ temperatureF = tempC*9. import java.

model.util. // Conecta la Vista con el Modelo } public void update(Observable t. } } 45 .println("La temperatura ha cambiado" + modelo. public Observador(Observado model) { modelo=model.Patrón OBSERVER Ejemplo: La clase Observer (la vista) public class Observador implements java.getF()). Object o) // Invocada desde el modelo { System.out.Observer { private Observado modelo.addObserver(this).

o. Observador2 ob2=new Observador2(o).5 Process exited with exit code 0.5).5 La temperatura ha cambiado45.setF(45.Patrón OBSERVER Ejemplo: El programa principal public static void main(String[] args) { Observado o=new Observado(). 46 . } The temperature has changed45. Observador ob=new Observador(o).

OBSERVABLE OBSERVER Ejemplo de patrón OBSERVER 47 .

... public class ObserverQuePinta extends Frame implements Observer{ VISTA Label label1 = new Label(); Panel panel1 = new Panel(); Observable suSubject; public interface Observer { void update(); public ObserverQuePinta(Observable s) {} suSubject = s; s.addObserver(this); } public void update() { String c = suSubject.getColor(); if (c.equals("ROJO")) panel1.setBackground(Color.red); else if (c.equals("VERDE")) panel1.setBackground(Color.green); else if (c.equals("AZUL")) panel1.setBackground(Color.blue); }}
48

MODELO public class Subject extends Observable { Choice choice1 = new Choice(); public Subject() { choice1.addItem("ROJO"); choice1.addItem("VERDE"); choice1.addItem("AZUL"); choice1.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(ItemEvent e) { setChanged(); notifyObservers(); }} } public String getColor() {return choice1.getSelectedItem();} }
49

Patrón OBSERVER
Inicialización

Subject s = new Subject(); Observer o1 = new ObserverQuePinta(s); Observer o2 = new ObserverQuePinta(s);

CREACIÓN DE OBJETOS SUBJECT Y OBSERVER
50

Patrón OBSERVER Adaptabilidad de la solución • Si se quisiera añadir un nuevo OBSERVER que en vez de pintar escribiera un número para cada color (1 si ROJO. ¿qué habría que hacer? A – Escribir nueva clase OBSERVER que implemente “notificar” • Si se quisiera cambiar el SUBJECT para escoger el color pinchando un Checkbox en vez de escogerlo de un Choice – Hay que sustituir el Subject y llamar a “notificar” de los observers cuando se seleccione un nuevo Checkbox 51 B . 2 si VERDE. 3 si AZUL).

.. else if (c. TextArea textArea1 = new TextArea(). public interface Observer { s.addObserver(this).getColor().equals("VERDE")) textArea1.append("NUEVO COLOR: "+3+"\n").append("NUEVO COLOR: "+1+"\n"). if (c. else if (c.append("NUEVO COLOR: "+2+"\n")... public void update() { } String c = suSubject. public class ObserverQueEscribeNums extends Frame implements Observer{ Label label1 = new Label(). .equals("ROJO")) textArea1.equals("AZUL")) textArea1.. Subject suSubject. } void update(). public ObserverQueEscribeNums(Subject s) { suSubject = s. }} 52 EXTENDER CON UN NUEVO OBSERVER A .

} })..event. checkbox1.getLabel(). y checkbox3 CheckboxGroup checkboxGroup1 = new CheckboxGroup().setLabel("VERDE"). checkbox2.setCheckboxGroup(checkboxGroup1).} } 53 .setLabel("ROJO"). public String getColor() { return checkboxGroup1.setLabel("AZUL"). notifyObservers()... // .getSelectedCheckbox().ItemListener() { public void itemStateChanged(ItemEvent e) { B setChanged()..awt..addItemListener(new java. public class Subject extends Observable { Checkbox checkbox1 = new Checkbox().. checkbox1. Checkbox checkbox2 = new Checkbox().CAMBIAR DE SUBJECT . // y checkbox3.. public Subject() { checkbox1.

54 .

Ventajas – Se permite cambiar el algoritmo dinámicamente – Se eliminan sentencias condicionales para seleccionar el algoritmo deseado 55 .Patrón STRATEGY Intención: – Encapsular algoritmos relacionados en clases y hacerlos intercambiables. – Se permite que la selección del algoritmo se haga según el objeto que se trate.

MétodoResolución1 Resolver () MétodoResolución2 Resolver () MétodoResolución3 Resolver () 56 .Patrón STRATEGY La solución SistemaLineal . MétodoResolución Resolver() instancia->Resolver(). Resolver () .....

La clase Cliente necesita ejecutar un método: operac(). …. Se pueden implementar todos ellos (en las clases StrConcrX) y ser trasparente a Cliente. Clase StrConcr2 operac() operac() …..Patrón STRATEGY Interfaz Strategy Clase Cliente …. 57 . que puede ser implementado siguiendo distintos algoritmos. Clase StrConcr1 1 usa 0. ….1 operac() ….

} // EL Cliente SIEMPRE SE EJECUTARÁ ASÍ: s. } Cliente c = new Cliente(new StrConcr1()).operac().Patrón STRATEGY Implementación class Cliente { Strategy s. // PARA SELECCIONAR EL ALGORITMO // SE ASIGNA A s LA INSTANCIA // DE LA SUBCLASE QUE LO IMPLEMENTA Cliente(Strategy str) {s = str. Se indica cuál es el algoritmo que se ejecutará 58 .

else if (cond2) operac2().. } • Sentencias condicionales para seleccionar el algoritmo • Si se quisiera añadir una nueva forma de ejecutar operac() entonces HABRÍA QUE CAMBIAR EL CÓDIGO DE LA CLASE Cliente 59 . else ..Patrón STRATEGY Implementación class Cliente { // EN VEZ DE: if (cond1) operac1().

Define una interfaz que declara métodos para acceder secuencialmente a la colección. • Ventajas: – La clase que accede a la colección solamente a través de dicho interfaz permanece independiente de la clase que implementa la interfaz.Patrón ITERATOR • Intención: – Proporcionar una forma de acceder a los elementos de una colección de objetos de manera secuencial sin revelar su representación interna. 60 .

IteradorConcreto hasNextItem() getNextItem() ♦Participantes ♦Iterador: define una interfaz para acceder a los elementos del agregado y recorrerlos ♦IteradorConcreto: implementa la interfaz de Iterador y mantiene la posición actual del recorrido ♦Agregado: define una interfaz para crear un objeto iterador ♦AgregadoConcreto: implementa la interfaz de creación del iterador 61 para devolver una instancia apropiada de IteradorConcreto .Patrón ITERATOR Interfaz Agregado CrearIterador() : Iterador Cliente Interfaz Iterador hasNextItem() getNextItem() AgregadoConcreto CrearIterador() : Iterador return new IteradorConcreto(this).

Patron ITERATOR en Java Interfaz Collection<T> elements() : Enumeration<T> Cliente Interfaz Enumeration<T> T hasMoreElements() void nextElement() class Vector<T> elements(): VectorEnumeration<T> class VectorEnumeration<T> T hasMoreElements() void nextElement() La clase VectorEnumeration. es la responsable de mantener un índice para recorrer la estructura Vector 62 .

Queue<Student> cola = new ListQueue<Student>().Patrón ITERATOR • Ejemplos en Java: Vector<Student> listOfStudents = new Vector<Student>(). while ( colaEnum. // PARA RECORRER EL VECTOR: Enumeration<Student> listEnum = listOfStudents.hasMoreElements() ) listEnum.elements(). while ( listEnum.elements().nextElement().hasMoreElements() ) colaEnum. 63 .nextElement().printStudent( ).printStudent(). // PARA RECORRER LA COLA: Enumeration<Student> colaEnum = cola.

Sign up to vote on this title
UsefulNot useful