patrones de comportamiento iterator, strategy, command, observer y visitor

Page 1

PATRONES DE COMPORTAMIENTO: ITERATOR, STRATEGY, COMMAND, OBSERVER Y VISITOR

J. J. F.

R. A. F.

Maestrante en Ingeniería del Software Universidad Mayor de San Andrés – LP, Bolivia Teléfono: 591-2@hotmail.com

Maestrante en Ingeniería del Software Universidad Mayor de San Andrés – LP, Bolivia Teléfono: 591-2@hotmail.com

Roger Saravia Aramayo

Y. C. S.

Maestrante en Ingeniería del Software Universidad Mayor de San Andrés – LP, Bolivia Teléfono: 591-2-2782666 rgusarav@hotmail.com

Maestrante en Ingeniería del Software Universidad Mayor de San Andrés – LP, Bolivia Teléfono: 591-7@hotmail.com

Resumen En este trabajo se desarrolla extensamente los patrones de comportamiento que emergen como parte del grupo del los patrones de diseño para la programación orientada a objetos; específicamente se tratan: Iterator, Strategy, Command, Observer y Visitor. Primero, se incluye una descripción general y características de los patrones de diseño y de comportamiento. Luego, se desglosa cada patrón de comportamiento exponiendo sus ventajas, estructura, consecuencias y hasta un ejemplo en el lenguaje Java en la mayoría de los casos. Al final, se hacen algunas conclusiones importantes sobre su uso.

Palabras Clave Patrones, Java, Comportamiento, Iterator, Strategy, Command, Observer, Visitor, UML, Objetos, Algoritmos, Clases, Métodos, Atributos, Desarrollo, Programación, Orientación a Objetos, Software, Problemas Recurrentes.


Índice

Resumen............................................................................................................................................... 1 Palabras Clave ..................................................................................................................................... 1 Índice ................................................................................................................................................... 2 1

Introducción ................................................................................................................................ 3

2

Objetivos....................................................................................................................................... 3

3

Marco Teórico ............................................................................................................................. 3

4

3.1

Breve Reseña Histórica....................................................................................................................3

3.2

Definiendo un Patrón .......................................................................................................................3

3.3

Patrones de Comportamiento .........................................................................................................4

Desarrollo Teórico-Práctico........................................................................................................ 4 4.1

Iterator ..............................................................................................................................................4

Motivación.................................................................................................................................................................. 5 Consecuencias del Patrón Iterator .............................................................................................................................. 6 Consideraciones.......................................................................................................................................................... 6

4.2

Strategy (Policy) ...............................................................................................................................7

Motivación.................................................................................................................................................................. 7

4.3

Command .........................................................................................................................................9

4.4

Observer .........................................................................................................................................10

Aplicación ................................................................................................................................................................ 12

4.5

Visitor ..............................................................................................................................................13

Consecuencias .......................................................................................................................................................... 14

5

Conclusiones .............................................................................................................................. 14

6

Referencias ................................................................................................................................ 15

2


1

Introducción El escenario de este proyecto se desenvuelve en el área de programación orientada a objetos; específicamente en la rama de patrones de diseño - división patrones de comportamiento. Los patrones de diseño emergen luego de décadas de programación donde ciertos tipos repetidos de comportamiento fueron divisados en el desarrollo de las aplicaciones. Los patrones mejoran la calidad del software, reducen el tiempo de diseño, y capturan las estructuras o modos de colaboración en soluciones a problemas de un dominio en particular.

2

Objetivos 

Desarrollar las características del patrón de comportamiento Iterator.

Desarrollar las características del patrón de comportamiento Strategy.

Desarrollar las características del patrón de comportamiento Comand.

Desarrollar las características del patrón de comportamiento Observer.

Desarrollar las características del patrón de comportamiento Visitor.

3

Marco Teórico

3.1

Breve Reseña Histórica Christopher Alexander escribió libros acerca de los patrones en ingeniería civil y arquitectura. La comunidad del software adoptó la idea de patrones basados en su trabajo. Los patrones fueron popularizados por el libro “Design Patterns: Elements of Reusable Object-Oriented Software” por Erich Gamma, Richard Helm, Ralph Johnson, y John Vlissides. Los patrones que ellos describieron no eran su invento pero sí eran documentos que mostraban diseños recurrentes en numerosos proyectos.

3.2

Definiendo un Patrón Los patrones tratan sobre problemas y soluciones. Los patrones nos permiten documentar un problema recurrente y su solución para un contexto en particular además de comunicar su solución a otros.

3


Cada patrón es una relación entre contexto, problema y solución. Algunas características de los patrones:

3.3

Son observados durante la experiencia.

Son típicamente escritos en formato estructurado.

Previenen reinventar la rueda.

Existen en diferentes niveles de abstracción.

Sufren continuas mejoras.

Son artefactos re-usables.

Comunican diseños y las mejores prácticas.

Pueden ser usados juntos para resolver grandes problemas.

Patrones de Comportamiento Uno de los tipos de patrones de diseño importantes al momento de realizar el diseño mismo de comunicación entre componentes, clases y objetos dentro del desarrollo de software, son los patrones de comportamiento. Los patrones de comportamiento caracterizan el modo en que las clases y objetos interactúan y se reparten la responsabilidad. Tienen que ver con las interacciones dinámicas entre sociedades de clases y objetos.

4

Desarrollo Teórico-Práctico

4.1

Iterator Iterator es uno los patrones más simples y es muy usado. El patrón Iterator permite moverse a través de una lista o colección de datos sin usar una interfaz estándar o sin tener que conocer los detalles de la representación interna de los datos. Adicionalmente, uno puede definir iteradores especiales que realizan ciertos procesamientos especiales y que retornan solo elementos específicos de la colección de datos.

4


Motivación Iterator es muy útil puesto que provee una manera definida de moverse a través de un conjunto de elementos sin exponer cómo lo hace. Iterator es una interfaz y puede ser implementada de la manera más adecuada y correspondiente con los datos que se están retornando. Se sugiere que la estructura de la interfaz sea la siguiente:

public interface Iterator { public Object First(); public Object Next(); public boolean isDone(); public Object CurrentItem(); } Iterator es una opción que viene ya implementada en Java:

public interface Enumeration { public boolean hasMoreElements(); public Object nextElement(); }

Enumeraciones en Java

El tipo Enumeration está incluido en las clases Vector y Hashtable. Ambas clases contienen un método elements que devuelve la Enumeración de los datos de la clase:

public Enumeration elements();

Este método elements() es un método que produce instancias de la clase Enumeración. Y para moverse a través de la lista uno podría usar por ejemplo el siguiente código:

Enumeration e = vector.elements(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); System.out.println(name); }

5


En adición, Hashtable proporciona el método keys que retorna una enumeración de las “keys” para cada elemento en la tabla:

public Enumeration keys();

Filtros

También se pueden definir filtered Enumerations que realizan algún cálculo sobre los datos antes de devolverlos. Por ejemplo, uno podría retornar los datos ordenados de una manera en particular o solo aquellos que encajan con cierto criterio.

Consecuencias del Patrón Iterator Modificación de datos:

Un problema significativo puede suceder si se cambian los datos durante la iteración.

Accesos privilegiado:

La clase Enumeration puede verse en la necesidad de acceso privilegiado a los datos de las estructuras de datos subyacentes del contenedor original de clase; todo esto antes de moverse por los datos.

Composites and Iterators

Iterator, o en nuestro caso, Enumerations, son una vía excelente de moverse a través de estructuras compuestas.

Consideraciones El iterador no es el único lugar donde se puede definir el algoritmo de recorrido. El agregado podría definir el algoritmo de recorrido y usar el iterador para almacenar solo el estado de la iteración. A este tipo de iterador se lo denomina cursor, ya que se limita a apuntar a la posición actual del agregado. Un cliente invocará al método Siguiente() sobre el agregado con el cursor como parámetro y la operación Siguiente() cambiará el estado del cursor.

6


Si el iterador es el responsable del algoritmo de recorrido, entonces es fácil usar diferentes algoritmos de iteración sobre el mismo agregado, y también puede ser más fácil reutilizar el mismo algoritmo sobre diferentes agregados. Por otro lado, el algoritmo de recorrido puede necesitar acceder a las variables privadas del agregado. Si es así, poner el algoritmo de recorrido en el iterador violaría la encapsulación del agregado.

Ejemplo

Un objeto que maneja la ejecución de consultas SQL, caché y procesamiento del resultado. Usualmente implementado como beans de sesión.

4.2

Strategy (Policy) Consiste en un número de algoritmos relacionados y encapsulados en una clase controladora llamada “Contexto”. El programa cliente puede seleccionar uno de esos algoritmos diferentes o en algunos casos el Contexto es el que selecciona el mejor. La intención es alternar fácilmente entre algoritmos sin sentencias condicionales.

Ilustración 1. Estructura Strategy (D. A. R.)

Motivación Un programa que requiere un servicio o función y que dispone de varias maneras de hacer eso, es un candidato para el patrón estrategia. Los programas eligen un algoritmo dependiendo de la eficiencia computacional o de la elección del usuario. Hay muchos casos en que los programas pueden hacer una misma cosa pero de distintas maneras. Por ejemplo:

Grabar archivos en diferentes formatos

Proceder con compresión usando algoritmos diferentes.

Usar diferentes saltos de línea para desplegar información.

7


Trazar la misma información en diferentes formatos: barras, torta o líneas.

Aplicaciones de robótica.

Para validar la entrada de datos en cuadros de diálogo.

Cuando muchas clases relacionadas difieren solo en su comportamiento.

La idea de Estrategia es encapsular varias estrategias en un simple módulo y proveer de una simple interfaz para elegir entre dichas estrategias. No todas ellas requieren ser miembros de una jerarquía de clase. No obstante deben tener implementada la misma interfaz.

El Contexto

El contexto es una especie de comandante de tráfico que decide cuál estrategia emplear. La decisión se basa en la solicitud del programa cliente y todo lo que tiene que hacer es que una variable apunte a una estrategia en concreto. Un vistazo al código en Java:

// aplicación de prueba class MainApp { public static void main(String[] args) { Context context; // Tres contextos con tres distintas estrategias context = new Context(new ConcreteStrategyA()); context.execute(); context = new Context(new ConcreteStrategyB()); context.execute(); context = new Context(new ConcreteStrategyC()); context.execute(); } } // Las clases que implementan una determinada estrategia deben incluir lo siguiente: interface IStrategy { void execute(); } // Primer algoritmo class ConcreteStrategyA implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyA.execute()" ); }

8


} // Segundo algoritmo class ConcreteStrategyB implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyB.execute()" ); } } // Tercer algoritmo class ConcreteStrategyC implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyC.execute()" ); } } // Configurado con el objeto ConcreteStrategy y referenciado al objeto Strategy class Context { IStrategy strategy; // Constructor public Context(IStrategy strategy) { this.strategy = strategy; } public void execute() { strategy.execute(); } }

4.3

Command El patrón Command envía una solicitud a un módulo específico. Este envío encierra dentro de un objeto un requerimiento para una acción específica y al objeto le da a su vez una interfaz pública. Esto permite al cliente hacer solicitudes sin conocer nada sobre la acción actual que será realizada y permite cambiar la acción sin afectar al mencionado programa cliente. Un propósito del patrón Command es mantener al programa y a los objetos de la interfaz de usuario completamente separados de la acción que ellos inician. En otras palabras, estos objetos de programa deberían estar completamente separados entre sí y no “saber” nada de cómo los otros objetos llevan su trabajo. Una interfaz de usuario podría recibir un comando e instruir al objeto Command cumplir sus responsabilidades. La interfaz de usuario no debería tener la necesidad de “saber” que tareas serán ejecutadas.

9


Ilustración 2. Estructura Command (D. A. R.)

ConcreteCommand: Define un vínculo entre un objeto Receiver y una acción, implementa Execute() invocando al método correspondiente de Receiver.

4.4

Cliente:

Crea un objeto ConcreteCommand y establece su receptor.

Invoker:

Pide a Command que lleve a cabo su petición.

Receiver:

Sabe cómo realizar las operaciones asociadas con la puesta en marcha de la petición.

Command:

Declara una interfaz para la ejecución de una operación.

Observer Define una dependencia entre objetos de uno (subject) a muchos (observers). Ciertos eventos son notificados por el subject a todos los observers que dependen de él, los cuales realizan una cierta tarea como consecuencia. Establece dos comportamientos comunes: 

Uno entre todos los objetos subjects.

Otro entre todos los objetos observers.

Para ello usa dos clases abstractas: Subject y Observer. Este patrón (algunas veces conocido como editor/subscriptor) es un patrón de diseño usado en programación para observar el estado de un objeto en un programa. Está relacionado con el principio de invocación implícita. Está usado como un sistema de detección de eventos. Es una característica muy interesante en términos del desarrollo de aplicaciones en tiempo real. Entre sus Objetivos:

10


Reducir al mínimo el acoplamiento entre las clases a las que pertenecen los objetos subjects y observers para aumentar la reusabilidad de dichas clases.

Para ello se usa las clases abstractas Subject y Observer que crean un primer nivel de abstracción en el que se incluyen todas las dependencias entre clases para que las clases concretas que heredan de ellas sean lo más independientes posibles.

Permitir un número ilimitado de objetos observers que observen a un cierto objeto subject.

Para ello la clase abstracta Subject tiene una lista de objetos observers a los que notificar en caso de que suceda algún evento de interés.

Subject:

Conoce a sus observadores que pueden ser de 0 a N y ofrece la posibilidad de añadir y eliminar observadores.

Observer:

Define la interfaz que sirve para notificar a los observadores los cambios realizados en el Subject.

ConcreteSubject;

Almacena el estado que es objeto de interés de los observadores y envía un mensaje a sus observadores cuando su estado cambia.

ConcreteObserver:

Mantiene una referencia a un ConcreteSubject Almacena el estado del Subject que le resulta de interés Implementa la interfaz de actualización de Observer para mantener la consistencia entre los dos estados.

Ilustración 3. Estructura Observer (D. A. R.)

11


Aplicación 

Cuando una abstracción tiene dos aspectos, uno dependiente del otro. La encapsulación de estos aspectos en objetos separados permite modificarlos y reutilizarlos de forma independiente.

Cuando un cambio en un objeto exige cambios en otros pero se desconoce a cuántos objetos afectan dichos cambios.

Cuando un objeto tiene que ser capaz de notificar a otros objetos sin saber nada más de esos objetos

. Clases en la API de Java para implementar el patrón Observer

Interfaz Observer:

public interface Observer

Una clase puede implementar la interfaz Observer cuando dicha clase quiera ser informada de los cambios que se produzcan en los objetos observados. Tiene un servicio que es el siguiente:

void update (Observable o, Object arg)

Este servicio es llamado cuando el objeto observado es modificado. Clase Observable:

public Class Observable extends Object

Esta clase representa un objeto Subject o “dato” en el modelo vista. Constructor:

Observable ()

Construye un objeto Subject con cero Observers. Nos ofrece los siguientes servicios:

void addObserver (Observer o) protected void clearChanged()

12


int countObservers() void deleteObserver (Observer o) void deleteObservers() boolean hasChanged() void notifyObservers() void notifyObservers (Object arg) protected void setChanged()

4.5

Visitor El patrón Visitor representa una operación que se lleva a cabo sobre los elementos de una estructura de objetos. Permite definir nuevas operaciones sin modificar las clases de los elementos sobre las que opera. Permite incluir nuevos métodos a una clase sin tener que modificarla. Muy utilizado en compiladores, intérpretes y analizadores de código.

Ilustración 4. Estructura Visitor (D. A. R.)

Visitor:

Declara una operación de visita para cada uno de los elementos concretos de la estructura de objetos.

13


ConcreteVisitor:

Implementa cada una de las operaciones declaradas por Visitor. Normalmente, cada operación implementa una parte de la labor global del visitor concreto, pudiendo almacenar información local.

Element:

Define la operación que le permite aceptar la visita de un Visitor.

ConcreteElement:

Implementa la operación de accept que se limita invocar su correspondiente método del Visitor.

ObjectStructure:

Gestiona la estructura de objetos y puede ofrecer una interfaz de alto nivel para permitir a los Visitor visitar a sus elementos.

Recomendado para: 

Estructuras jerárquicas (árboles).

Muchas clases poco relacionadas entre sí.

Estructura de objetos con diferentes interfaces y posibilidad de ampliación.

Estructura con altas probabilidades de incluir de nuevos métodos

Compiladores, interpretes...

Consecuencias

5

Visitor facilita la inclusión de nuevas operaciones.

Visitor agrupa las operaciones relacionadas entre sí.

La inclusión de nuevos ConcreteElements es una operación costosa.

Visitor ofrece la posibilidad de visitar distintas jerarquías de objetos u objetos no relacionados por un padre común.

Gracias a Visitor es posible acumular el estado de una operación global a través de una estructura.

Este patrón supone que la interfaz que ofrecen las clases que forman la estructura de objetos es lo suficientemente completa como para permitir su labor a las posibles nuevas operaciones.

Conclusiones Los patrones de comportamiento son técnicas comunes recopiladas de la experiencia luego de muchos años de programación y desarrollo. Varios patrones introducen un objeto que siempre se usa como argumento (Visitor, Command, y otros).

14


El patrón Observer distribuye la comunicación introduciendo objetos Observador y Sujeto. El patrón Command permite el desacoplamiento usando un objeto que define un enlace entre un emisor y un receptor. El patrón Observer desacopla a los emisores de los receptores. El patrón Iterator está entre los más usados por su capacidad de ciclar por medio de las colecciones de objetos. El patrón Strategy puede ser muy útil para que un programa pueda mutar y actuar de acuerdo a ciertas condiciones dadas con relación al software y hardware.

6

Referencias OBJECT ORIENTED DESIGN (2006)

“Software Design Principles and Design Patterns”. [En red]. Disponible en: http://www.oodesign.com

WIKIPEDIA ENCICLOPEDIA (2007)

“Strategy Pattern”. [En red]. Disponible en: http://en.wikipedia.org/wiki/Strategy_pattern

DODERO Y FERNANDEZ (2004)

"Patrones de Comportamiento". Carlos III de Madrid. España.

Universidad

CARLOS CARRERAS (2005)

"Patrones de Comportamiento". Politécnica de Madrid. España.

Universidad

JAMES W. COOPER (1998)

“The Design Patterns Addison-Wesley. USA.

Java

Companion”.

15


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.