1 .
Dedicatoria
2 .
Resumen
3 .
1.- Introducción
4 .
1.1.- Value Object
5 .
1.2. Session Façade
6 .
1.3 Data Access Object
7 .
2. Caso de estudio
8 .
3. Implementación
9 .
Conclusiones
10 .
Recursos del artículo
11 .
Bibliografía general
Dedicatoria
Al maestro Sr. Patricio Molina, mi profesor de computación de la
infancia, que en paz descanse. Su trabajo de hace más de 10 años
aproximadamente ha tenido sus primeros frutos. Espero que desde el
más allá pueda apreciar el resultado de meses de paciencia con un
niño de 10 a 12 años aproximadamente que solo deseaba jugar.
Ningún patrón de diseño puede entregar la experiencia que otorga
un verdadero maestro como lo fue el señor Patricio Molina.
Resumen
El siguiente documento tiene por objetivo definir y aplicar los
patrones de diseño Session Façade, Data Access Object y Value Objet
a un ejemplo particular.
Para lograr este objetivo, se define que son los patrones J2EE,
para posteriormente concentrarnos en la definición de los patrones
de estudio. A continuación, se define un caso de estudio en el cual
se aplican técnicas de análisis y diseño orientado a objetos,
ilustrando la aplicación de los patrones directamente en la fase de
diseño. Finalmente, se desarrolla una aplicación web de baja escala,
la que implementará una solución a la problemática del caso de
estudio en JSP / Struts / JDBC.
Los resultados del estudio permiten a los desarrolladores J2EE
que no tienen conocimientos sobre el tema de patrones, comprender su
aplicación y aprender su utilización por medio del ejemplo.
1.- Introducción
Sun Microsystem provee en su sitio web [SUN03-1] [SUN03-2] un
conjunto de patrones que pueden ser usados en el contexto del diseño
de aplicaciones Java 2 Enterprise Edition, J2EE. Los patrones de
diseño J2EE consisten en soluciones recurrentes y documentadas
de problemas comunes de diseño de aplicaciones J2EE. Muchas de estas
soluciones se basan en los patrones de Gamma et al. [GAM95], así que
se podrán encontrar soluciones J2EE que son aplicadas al diseño de
aplicaciones de software en general.
Un patrón J2EE consiste en un documento basado en una plantilla
que define las siguientes secciones:
- Contexto: Juego de entornos bajo los cuales el patrón existe
- Problema: Describe el problema de diseño enfrentado por el
desarrollador.
- Motivación: Lista de las razones y motivaciones que afectan al
problema y a la solución. Esta lista resalta la razón del porqué
se debe elegir utilizar el patrón en discusión en un problema de
diseño y de la justificación de su utilización.
- Solución: Describe el acercamiento a la solución brevemente y
los elementos de la solución en detalle. Esta sección contiene 2
subsecciones: Estructura: Diagrama de clases que definen los
objetos y relaciones entre estos.
- Estrategias: Describen diferentes formas de cómo un patrón
puede ser implementado.
- Consecuencias: Los trade-off (ventajas y desventajas) cuando
se aplica el patrón.
A continuación, se definen los patrones J2EE Value Object,
Session Façade y DAO..
1.1.- Value Object
Contexto
Las aplicaciones cliente necesitan comunicar, transportar e
intercambiar datos de negocios con los Enterprise Java Beans,
objetos JDBC y otros objetos.
Problema
- Cada llamada a get y set de un objeto remoto implica una
invocación remota, lo que afecta directamente en la escalabilidad
de una aplicación.
- El paso de los atributos de un objeto de dominio (por ejemplo,
Consumidores) a un método puede conducir a métodos con muchos
argumentos, y cada modificación de un atributo del objeto de
dominio afectará la signatura de todos los métodos que usen este
objeto, teniendo con ello problemas de acoplamiento y
mantenibilidad.
Motivación
- Las aplicaciones J2EE generalmente hacen uso de EJB para la
implementación de los componentes de negocio, lo que implica que
cada llamada a una propiedad de un entity bean por medio de los
métodos get/set signifi
caría una llamada remota.
- El cliente requiere más de un atributo del componente remoto,
lo que conduce a varias llamadas de red (ej, ingreso de un
Consumidor).
Solución
Se debe usar una clase que implemente el interfaz Serializable
(redefinir el metodo toString() ), en donde sus propiedades miembro
pueden variar según el tipo de enfoque:
Si se necesita modelar una tabla relacional o similar, las
propiedades de la clase serían las mismas que los campos de la tabla
relacional. Este enfoque se denomina Domain Value Object [MAR02].
Si se necesita encapsular atributos de varias tablas en una
petición (por ejemplo, un carrito de compra, con el id de un
cliente, el id y cantidad de un producto), se crea una clase que
combine todos los atributos que son requeridos. Este enfoque se
denomina Custom Value Object [MAR02].
En una aplicación que no utilice un VO para una operación de
negocios, se tendría la siguiente signatura en un método crear:
public void crearConsumidor(String rut, String nombre,
String Apellido, Calendar edad….)
Es claro que la signatura es muy larga y difícil de escribir, y
que su dificultad de escritura es proporcional a la cantidad de
campos de una tabla.
Sin embargo:
public void crearConsumidor(ConsumidorVO vo)
Provee de una signatura mucho más sencilla que la anterior,
puesto que se envía una referencia del objeto consumidor, el cual
encapsula todos los datos requeridos.
La estructura del patrón es la siguiente:
Consecuencias
- En el contexto de aplicaciones remota, se logra una mayor
eficiencia, puesto que reduce el envío de mensajes por red.
- En el contexto de JDBC, permite representar un conjunto de
atributos procedentes de uno o varios objetos de dominio,
representados por la signatura método (VO) en ves de método (arg1,
arg2, arg3…).
- Un Value Object puede contener información obsoleta si se
pretende usar en una actualización posterior en otra transacción.
Esto se puede corregir con el patrón Versión Number [MAR02].
Ejemplos
ConsultaVO.java
o
ProductoSoftwareVO.java
1.2. Session Façade
Contexto
Clases Java comunes o EJB encapsulan lógica y datos de negocios,
exponiendo sus interfaces y la complejidad de los servicios
distribuidos a la capa cliente.
Problema
En un método de aplicaciones donde se utiliza la arquitectura
estratificada (o por capas), se pueden presentar los siguientes
problemas:
- Acoplamiento fuerte, provocado por la dependencia directa
entre los clientes y los objetos de negocio.
- Demasiadas llamadas a operaciones entre el cliente y el
servidor, abocando a problemas de rendimiento de red (en el caso
de EJB).
- Falta de una estrategia de acceso uniforme de los clientes,
exponiendo los objetos de negocio a una mala utilización.
Motivación
- Proporcionar a los clientes un interfaz sencillo que oculte
todas las interacciones complejas entre los componentes de
negocio.
- Ocultar al cliente las interacciones y las interdependencias
entre los componentes de negocio, permitiendo de esta forma el
aumento de flexibilidad y evitar que los cambios en los objetos de
negocio repercutan en errores en la vista.
- Evitar la exposición directa de los objetos de negocios a los
clientes, para mantener el acoplamiento entre las dos capas al
mínimo.
- Centralizar los casos de uso en métodos centralizados sobre
una clase.
Solución
Usar un session bean (para el caso de aplicaciones EJB) o una
clase java común que encapsule la complejidad de las interacciones
entre los objetos de negocio participantes en un flujo de trabajo
(workflow). El session façade maneja los objetos de negocios y
proporciona un servicio de acceso uniforme a los cliente. Es decir,
el cliente (JSP, Swing, etc) no tratará con los EJB ni con la
complejidad del acceso remoto, ni con JDBC, sino que trabajará con
colecciones y Value's Object. .
La estructura del patrón es la siguiente
Consecuencias
- Introduce una capa extra entre el Modelo y el Controlador:
Agregando esta capa, se puede modelar los casos de uso de una
forma centralizada, logrando también centralizar todo el
acoplamiento a esta capa intermedia.
- Expone un interfaz uniforme para el acceso al Modelo.
- Cuando se utiliza con EJB, reduce el número de invocaciones
remotas, aumentando la escalabilidad.
- Simplifica la gestión de transacciones y el mantenimiento de
los casos de uso.
Ejemplos
ProductoSoftwareFacade.java
1.3 Data Access Object
Contexto
El acceso a los datos varía según el soporte persistente y el
proveedor.
Problema
- La poca homogeneidad del almacenamiento persistente produce
distintas implementaciones para lograr la accesibilidad (la
iimplementación de operaciones sobre un archivo de texto plano es
distinta a la realizada sobre un motor de base de datos, aunque se
requiera de ambos las mismas operaciones)). Un cambio en el
sistema de almacenamiento (cambio de proveedor de bd o de formato)
puede conducir a una reimplentación de los componentes de datos y
componentes vinculados (los que requieren estos datos).
- Con el API de JDBC se puede acceder de una forma estándar a
los servidores de bases de datos relacional. Sin embargo, la
implementación del lenguaje SQL puede variar según el propietario,
aunque se suponga que es un estándar (por ejemplo, las operaciones
para recuperar el autonumérico de un registro ingresado no es
igual en Oracle que en MySQL o SQLServer).
- El acceso a datos de sistemas no relacionales incurre en la
utilización de un API no propietario, por lo que se aumenta la
dependencia entre el código de la aplicación y el código del
acceso a datos.
- Introducir el código de conectividad en todos los componentes
que requieren de acceso hace difícil la mantención y la migración
cuando se desea cambiar la fuente de datos.
Motivación
- Los componentes de la aplicación necesitan recuperar y
almacenar información desde almacenamientos persistentes y otras
fuentes de datos variadas (includos archivos de texto, planillas
de cálculo, etc). Además, puede variar los proveedores, por lo que
se tiene el problema del SQL propietario.
- Una API de datos que exponga al cliente un conjunto de
operaciones comunes lograría reducir el acomplamiento y
dependencias de la implementación. Por ejemplo, una tabla de
clientes en un modelo relacional para el proveedor Oracle o MySQL
tiene las mismas operaciones: agregar, eliminar, modificar, etc.
Sin embargo, algunas operaciones pueden tener distintas
implementaciones (porque el SQL para esa acción puede ser distinto
según el proveedor), pero esto sería independiente para los
clientes (por medio de una factory)
- Los componentes necesitan ser transparentes al almacenamiento
persistente real o la implementación de la fuente de datos para
proporcionar una portabilidad y migración sencillas a diferentes
productos, tipos de almacenamiento y tipos de fuentes de datos.
Solución
- Utilizar un Data Access Object (DAO) para abstraer y
encapsular todos los accesos a la fuente de datos, logrando así
desacoplar la lógica de negocios de la lógica de acceso a datos.
El DAO maneja la conexión con la fuente de datos para obtener y
almacenar datos.
- El desacoplamiento de la lógica de negocios con el acceso a
datos permite crear implementaciones plugables del DAO, con solo
seleccionar el tipo de fuente de datos durante la
instalación/configuración de una aplicación.
Estructura
Consecuencias
- Flexibilidad en la instalación/configuración de una
aplicación.
- Independencia del vendedor de la fuente de datos.
- Independencia del recurso (base de datos relacional, base de
datos orientado a objetos, ficheros planos, etc.).
- Reduce la complejidad de la implementación de la lógica de
negocios (Session Façades)
- Más complejidad en el diseño, debido principalmente al
conjunto de clases que colaboran en el DAO y en forma general,
cada DAO es utilizado para modelar una tabla del modelo
relacional.
Ejemplo
AbstractSQLConsultaDAO.java ,
SQLConsultaDAO.java,
JDBC3CCSQLConsultaDAO.java,
SQLConsultaDAOFactory.java
2. Caso de estudio
Para aplicar estos dos patrones J2EE, se presentará un caso de
estudio de baja escala, en el cual se aplicará en forma directa los
patrones de diseño vistos anteriormente.
El caso de estudio se enmarca en el grupo de desarrollo
Inukisoft. Esta empresa basa su principal actividad en el desarrollo
de software, por lo que requiere de una web que permita a los
clientes ver la oferta de productos y enviar consultas /
sugerencias. Los administradores de la web de Inukisoft deben poder
revisar las consultas y actualizar el catálogo de productos, con una
cuenta exclusiva para usuarios administradores. Se especifica que se
requiere de una única cuenta de administración, por lo que no se
deberá registrar una lista de usuarios.
Cada producto incluye su identificador, nombre, descripción. Los
administradores podrán actualizar todos los datos de estos
productos, y eliminarlos si lo consideran pertinente.
Las siguientes funciones se pueden resumir en el siguiente
diagrama de casos de uso:
En base a este diagrama de casos de uso, se pueden identificar
algunos objetos de dominio candidatos: Producto de software,
Catálogo, Consulta, Cliente y Administrador. Definiendo un diagrama
de clases para armar el modelo conceptual, quedaría:
Ya definido un bosquejo del análisis, toca ir al diseño de la
aplicación. Para ello, se define el modelo de datos que se
utilizará.
| Atributo / Tipo |
Descripción del atributo |
| id / entero largo sin signo autonumérico |
Identifica a cada consulta con un número correlativo. |
| consulta / texto largo 255 |
El texto de la consulta efectuada por el cliente |
| fecha / tipo fecha timestamp |
La hora y fecha de la consulta |
| Tabla: |
ProductoSoftware |
| Atributo / Tipo |
Descripción del atributo |
| id / entero largo sin signo autonumérico |
id / entero largo sin signo autonumérico |
| nombre / texto largo 50 |
Describe las funcionalidades del producto |
| descripcion / texto largo 1000 |
La hora y fecha de la consulta |
| precio / flotante sin signo |
El precio del producto de software |
Los otros elementos del modelo conceptual no están incluidos en
el modelo relacional, puesto que no son entidades que almacenan
cantidades de datos.
Ya con los objetos de dominio persistentes definidos, se puede
entonces aplicar directamente el patrón Domain Value Object sobre
las tablas Consulta y ProductoSoftware, por lo que se obtendría las
clases
ConsultaVO y
ProductoSoftwareVO.
Ya generalizadas las tablas del modelo relacional en clases, se
debe a continuación aplicar el patrón DAO a las tablas Consulta y
Producto de Software. Bellas [BEL03] propone un esquema estructural
para los DAO's, el cual se reutilizará este diseño para la tabla
Consulta:
| Tabla: |
Consulta |
| Clase / Interface |
Descripción |
| SQLConsultaDAO |
Interface que define todas las operaciones de acción y
consulta de la tabla Consulta |
| AbstractSQLConsultaDAO |
Clase Abstracta que implementa SQLConsultaDAO. Los métodos
implementados en la clase abstracta son los que son
independiente de plataforma (en general son todos, a excepción
del método create() ). |
| JDBC3CCConsultaDAO |
Subclase de AbstractSQLConsultaDAO, la cual es una clase
concreta y final que implementa los métodos dependientes de la
plataforma. En general, se implementa el método create(),
puesto que el campo clave de la tabla es un autonumérico, por
lo que la estrategia de recuperación, en este caso, es por
DriverJDBC del tipo 3. |
| SQLConsultaDAOFactory |
Clase que implementa el patrón de diseño Factory Method
[GAM95]. Esta clase define cual subclase de
AbstractSQLConsultaDAO debe ser instanciada cuando se utiliza
el DAOConsulta. |
El diagrama de clases de este DAO queda representado de la
siguiente manera:
Podríamos reutilizar este diseño de clases para la tabla
“ProductoSoftware”, por lo que se tendría terminado el Modelo de
Tablas del sistema.
El siguiente paso del diseño es definir donde van a ir
implementados los casos de uso. Para ello, se puede aplicar
directamente el patrón Session Façade, donde se definirán todas las
operaciones de los casos de uso.
La façade es una clase concreta, definida de la siguiente
forma:
package inukisoft.patronesj2ee.facade;
public class ProductoSoftwareFacade {
public ProductoSoftwareVO createProductoSoftware(ProductoSoftwareVO vo)
throws InternalErrorException,DataBaseException {}
public ConsultaVO createConsulta(ConsultaVO vo)
throws InternalErrorException,DataBaseException {}
public Collection listConsulta()
throws InternalErrorException {}
public Collection listProductoSoftware()
throws InternalErrorException {}
public void removeProductoSoftware(Long softwareIdentifier)
throws InternalErrorException {}
public void removeConsulta(Long consultaIdentifier)
throws InternalErrorException { }
public void updateProductoSoftware(ProductoSoftwareVO vo)
throws InternalErrorException, DataBaseException {}
public ProductoSoftwareVO findProductoSoftware(Long softwareIdentifier)
throws InternalErrorException,DataBaseException {
}
}
Esta façade será el punto de acceso a todas las funcionalidades
del sistema. En una arquitectúra MVC (Modelo Vista Control), los
DAO’s y el VO representan la capa Modelo. La Vista puede ser
representada por una aplicación Swing, JSP o Applet. La vista se
comunica con las clases controlador, las cuales son las que se
comunican a su vez con la façade del sistema. De esta forma, se
tiene una arquitectura general del software con menos acoplamiento,
lo que permite trabajar con el modelo de forma independiente a la
vista (potenciando la separación de roles de trabajo, por ejemplo,
equipo de desarrollo del Modelo, equipo de desarrollo de la Vista y
Control, etc.)
La siguiente fase del diseño es definir la vista que se
favorecerá del Modelo. Según el caso de estudio, se requiere de una
WebApp, por lo que las vistas serán implementadas como JSP y las
clases controlador serán definidas como Servlets Action (subclase de
Action de Struts) que invocan a los datos de la façade (para evitar
que la vista se comunique directamente con la façade del sistema).
Para definir los elementos de la vista, se requiere del diseño de la
navegación, la cual será jerárquica:
Mapa de navegación / componentes de la
vista Administrador (1)
También incluye la siguiente jerarquía:
La navegación de la vista Cliente queda definida de la siguiente
forma:
Los servlets action cumplen el rol de controlador de flujo de las
acciones, seteando los datos que deben presentarse en las páginas
JSP, y también son utilizados para invocar a los métodos de negocios
definidos en la façade.
3. Implementación
En la implementación se deben codificar los modelos de clases
obtenidos del diseño (en este caso, en un diseño logrado con la
aplicación directa de los patrones de diseño). Se debe tener en
cuenta que el patrón de diseño representa una solución de diseño,
teniendo como objetivo la reutilización. Sin embargo, la
codificación del patrón de diseño a lenguaje Java no conduce
necesariamente a componentes reutilizables, por lo que se deberán
utilizar otras herramientas para hacer reutilizable el código
obtenido. En esta investigación se utilizó el Refactoring de Eclipse
para reutilizar el código de las clases, utilizando un DAO de otro
proyecto anterior, para luego adaptar el nombre, la ruta de los
paquetes, y la redefinición del método (en general, cambiar el SQL).
Las vinculaciones y correcciones de nombres son realizadas por el
IDE. Esta técnica es útil para los DAO’s que tienen pocos
campos y que cumplen las mismas funcionalidades básicas (por
ejemplo, una tabla pais (id,descripción) y otra tabla
categorias (id, categoria) las que son utilizadas para llenar los
comboBox de un formulario).
La implementación del Modelo Vista Control se realizó en Struts
1.1 [APA02], aconsejando la siguiente metodología en la
implementación del mapa de acciones [URZ03]:
- Definir el mapeo correspondiente a la nueva acción en el
archivo struts-config.xml, indicando el nombre de la acción, y la
clase Action que ejecutará las acciones correspondientes, el
nombre del FormBean que validará los datos, el alcance que tendrán
esos datos, de donde será referenciada y quien desplegará los
datos para los ActionForward definidos en el servlet. (ver
struts-config.xml)
- Escribir el BeanForm, y realizar las validaciones
correspondientes para asegurar que los datos lleguen al
controlador (Action). (ver
ProductoSoftwareForm.java)
- Escribir el Action Servlet, el cual ejecutará las acciones del
requerimiento (típicamente una invocación a la façade, la
asignación de valores al FormBean y la asignación de valores
asociados a la Request). (ver
EditVerCatalogoAction.java)
- Escribir el o los archivos JSP que generará la vista para el
usuario. Se debe tener especial cuidado con los beans y atributos
que se utilizarán en este archivo ya que deben estar definidos en
el FormBean e ingresados como atributos al requerimiento que
recibe la página JSP.(ver
VerCatalogo.jsp)
Para implementar los componentes de la vista, se utiliza Java
Standar Tag Library (JSTL), puesto que consiste en una solución,
basada en XML, que sustituye el scriptlet incristado de la páginas
JSP por tags XML [PAL03]. Este tipo de solución permite adecuar la
vista a los roles que no están familiarisados con el código Java,
como por ejemplo, los diseñadores. De esta forma, se mejora la
separación de roles de trabajo.
Conclusiones
La implementación de patrones J2EE no es trivial en los
desarrollos de aplicaciones empresariales. Los desarrolladores
necesitan conocer propuestas metodológicas para una correcta
implementación de los patrones. La investigación entrega un aporte
metológico, junto con un producto de baja escala con ejemplos de
implementación.
El código fuente del caso de estudio, incluido en la
investigación, puede ayudar a comprender la implementación del
patrón, pero debe quedar claro que los patrones no son las
respuestas únicas a un problema, sino que más bien representan una
solución estructural y de comportamiento para un problema de diseño
recurrente.
Recursos del artículo
Bibliografía general
- [ALE77] Alexander, Christopher. A Pattern Language:
Towns/Buildings/Construction. USA. Oxford University Press.
1977.
- [APA02] Apache Software Foundation. The Apache Struts Web
Application Framework, 2002.Disponible en http://jakarta.apache.org/struts/
- [BAR03] Barrios Nuñez, Juan Manual. Investigación de la
Plataforma J2EE y su Aplicación Práctica. Memoria para optar al
título de Ingeniero Civil en Computación,Universidad de Chile, 2003.
p.116
- [BEL03] Bellas Permuy, Fernando. Apuntes y código fuente de la
asignatura “Integración de Sistemas 2003”. Disponible en http://www.tic.udc.es/~fbellas/teaching/is.
- [BEL03-2] Bellas Permuy, Fernando. Un Enfoque Práctico Basado en
Patrones de Diseño para la Enseñanza de J2EE. Universidad de A
Coruña año 2003. Disponible en http://www.tic.udc.es/~fbellas
- [BOO99] Booch, Grady et al. El Lenguaje Unificado de
Modelamiento. España. Addison Wesley. 1999. p.432
- [DIA03] Días, Moises et al. Traducción al español del catálogo de
patrones de diseño J2EE para la capa de presentación y negocios.
2003. Disponible en http://www.programacion.net/java/tutorial/patrones2/
- [GAM95] Gamma, Erich et al. Design Patterns: Elements of Reusable
Object-Oriented Software. Holanda. Addison Wesley. 1995. p.395
- [GON03] González Calero, Pedro et al. Apuntes del curso Patrones
de Diseño Orientado a Objetos. 2003. Disponible en http://www.ucm.es/info/dsip/DOOCT-PDDOO.html
- [GUE03] Guerrero, Luis. Apuntes del curso de Análisis y Diseño
Orientado a Objetos. 2003. Disponible en http://www.dcc.uchile.cl/~luguerre/cc40b
- [HUS02] Husted, Ted. idioms struts. 2002 Disponible en http://husted.com/struts/catalog.html
- [JAW99] Jaworski, James. Java 1.2 Al Descubierto. Madrid.
Prentice Hall. 1999. p.1344
- [MAR02] Marinescu, Floyd. EJB Design Patterns: Advanced Patterns,
Pro-cesses, and Idioms. USA. John Wiley. 2002. p.259
- [MID02] Middleware Company. J2EE and .NET Application Server and
Web Service Benchmark
- [PAL03] Palos, Juan Antonio. Estandarizando JSP. 2004 Disponible
en http://www.programacion.com/java/tutorial/jstl1/2/
- [PAL02] Palos, Juan Antonio. El API Struts. 2002. Disponible en
http://www.programacion.com/tutorial.struts.html.
- [PRE02] Pressman, Roger. Ingeniería de Software: Un Enfoque
Práctico. Mexico. McGraw Hill. 2002. p.601
- [SUN03-1] Sun Microsystem. Core J2EE Patterns Index. 2003.
Disponible en http://java.sun.com/blueprints/corej2eepatterns/index.html
- [SUN03-2] Sun Microsystem. Enterprise Java Technologies Tech
Tips. 2003. Disponible en http://java.sun.com/developer/EJTechTips/
- [URZ03] Urzúa Reinoso, José Andrés. Diseño e Implementación de un
Nuevo Sistema de Facturación Para Nic Chile. Memoria para optar al
título de Ingeniero Civil en Computación,Universidad de Chile, 2003.
p.130. Disponible en http://nicolette.nic.cl/~jourzua/personal/files/memoria.pdf
- [VIL02] Vilches Vásquez, Juan Antonio. Generación Automática de
Encuestas Web Usando Patrones de Diseño. Memoria para optar al
título de Ingeniero Civil en Computación, Universidad de Chile,
2002. p.78
- [WEB1] Varios Autores. Estructura de patrones de diseño Gamma et
al. 2003.Disponible en http://www.tml.hut.fi/~pnr/GoF-models/html/
- [WEB2] Varios Autores. Patterns of Java and Distributed
Computing. 2003. Disponible en http://cmcrossroads.com/bradapp/javapats.html
- [WES02] Wesner, Stephan. Struts Tutorial. 2002. p.51. Disponible
en http://www.stephanwiesner.de/