patrones de diseño (capa de datos)

20

Click here to load reader

Upload: manuel-jumilla-pandero

Post on 03-Jul-2015

250 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Patrones de Diseño (Capa de Datos)

Patrones de Diseño J2EEIntroducción a los Patrones

¿Qué es un Patrón?

Algunas personas definen un patrón como una solución recurrente para un problema en un contexto. Estos términos -- contexto, problema y solución -- merecen una pequeña explicación. Primero, ¿qué es un contexto? Un contexto es el entorno, situación, o condiciones interrelacionadas dentro de las cuales existe algo. Segúndo, ¿qué es un problema? Un problema es una cuestión insatisfecha, algo que se necesita investigar y resolver. Un problema se puede especificar mediante un conjunto de causas y efectos. Normalmenete un problema está restringido al contexto en el que ocurre. Finalmente, la solución se refiere a la respuesta al problema dentro de un contexto que ayuda a resolver las dificultades.

Entonces, si tenemos una solución a un problema en un contexto, ¿es un patrón? No necesariamente. También necesitamos asociar la característica de recurrencia con la definición de un patrón. ¿Eso es todo? Quizás no. Los patrones deberían comunicar soluciones de diseño a los desarrolladores y arquitectos que los leen y los utilizan. Como puedes ver, aunque el concepto de patrón es bastante simple, definir realmente el término es muy complejo.

Hemos señalado sólo las referencias para que puedas indagar en más profundidad en la historia de los patrones y aprender sobre ellos en otras áreas. Sin embargo, deberías tener en mente que la definición de patrón que hemos adoptado funciona. En nuestro catálogo, se describe un patrón de acuerdo a sus principales características: contexto, problema y solucion, junto con otros aspectos importantes, como causas y consecuencias. La página que describe la plantilla de patrones explica estas características en más detalle.

Abstracción de Patrones

Un patrón describe, con algún nivel de abtrascción, una solución experta a un problema. Normalmente, un patrón está documentado en forma de una plantilla. Aunque es una práctica estándar documentar los patrones en un formato de plantilla especializado, esto no significa que sea la única forma de hacerlo. Además, hay tantos formatos de plantillas como autores de patrones, esto permite la creatividad en la documentación de patrones.

Los patrones solucionan problemas que existen en muchos niveles de abstracción. Hay patrones que describen soluciones para todo, desde el análisis hasta el diseño y desde la arquitectura hasta la implementación. Además, los patrones existen en diversaa áreas de interés y tecnologías. Por ejemplo, hay un patrón que describe como trabajar con un lenguaje de programación específico o un segmento de la industria específico, como la sanidad.

Identificar un Patrón

Se han manejado muchos proyectos J2EE en Sun Java Center, y, con el tiempo, se ha notado que ocurren problemas similares en todos estos proyectos. También se ha visto que han emergido soluciones similares para todos estos problemas. Aunque las estrategias de implementación variaran, las soluciones generales eran bastante similares. Cuando se ha visto un problema y una solución recurrentes, se ha intentado identificar y documentar sus características usando la plantilla de patrón. Los candidatos a patrones no se han añadido al catálogo de patrones hasta que no se ha podido observar y documentar su utilización varias veces en diferentes proyectos. También se emprendió el procesamiento de significado de los patrones buscando patrones en soluciones ya implementadas. Luego, hay una "Regla de Tres", como se la conoce en la comunidad de los patrones. Esta regla es una guiá para ascender un patrón candidato al catálogo de patrones. De acuerdo a esta regla, una solución permanece como un patrón candidato hasta que se ha verificado en al menos tres sistemas diferentes. Ciertamente que hay mucho espacio para la interpretación en reglas como ésta, pero ayudan a proporcionar un contexto para la identificación de patrones. Muchas veces, soluciones similares podrían representar un sólo patrón. Cuando se decide cómo formar un patrón, es importante considerar cual es la mejor forma de comunicar la solución. Algunas veces, un nombre indenpendiente mejora la comunicación entre los desarrolladores. Si es así, es mejor considerar la documentación de dos soluciones similares como dos patrones diferentes. Por otro lado, podría ser mejor comunicar la solución destilando las ideas similares en una combinación de patrón/estrategia.

Patrones contra Estrategias

Cuando se empezó a documentar los patrones J2EE, se tomó la decisión de documentarlos con un nivel de abstracción relativamente alto. Al mismo tiempo, cada patrón incluye varias estrategias que

Page 2: Patrones de Diseño (Capa de Datos)

proporcionan detalles de su implementación a bajo nivel. A través de las estrategias, cada patrón documenta una solución con varios niveles de abstracción. Se ha reconocido que se podría haber documentado algunas de estas estrategias como patrones por sí mismas. Sin embargo, se ha creído que la estructura de plantilla actual comunica más claramente la relación de las estrategias con la estructura de patrón de alto nivel en que se ha incluido.

Se han anotado algunos de los problemas con respecto a la relación entre las estrategias y los patrones:

Los patrones existen a un nivel de abstracción más alto que las estrategias. Los patrones incluyen implementaciones más comunes o más recomendadas que las

estrategias. Las estrategias proporcionan un punto de extensibilidad para cada patrón. Los desarrolladores

descubren e inventan nuevas formas de implementar patrones, produciendo nuevas estrategias para patrones bien-conocidos.

Las estrategias promueven una mejor comunicación, proporcionando nombres para aspectos de bajo nivel de una solución particular.

El Catálogo de Patrones J2EE (Core J2EE Patterns)

Page 3: Patrones de Diseño (Capa de Datos)

Abajo puedes ver una representación gráfica del Catálogo de Patrones Principales de J2EE (Core J2EE Patterns):

Catálogo de patrones J2EE

Capa de Presentación

Decorating Filter / Intercepting

Un objeto que está entre el cliente y los componentes Web. Este procesa las peticiones y las respuestas.

Page 4: Patrones de Diseño (Capa de Datos)

Filter

Front Controller/ Front Component

Un objeto que acepta todos los requerimientos de un cliente y los direcciona a manejadores apropiados. El patrón Front Controller podría dividir la funcionalidad en 2 diferentes objetos: el Front Controller y el Dispatcher. En ese caso, El Front Controller acepta todos los requerimientos de un cliente y realiza la autenticación, y el Dispatcher direcciona los requerimientos a manejadores apropiados.

View HelperUn objeto helper que encapsula la lógica de acceso a datos en beneficio de los componentes de la presentación. Por ejemplo, los JavaBeans pueden ser usados como patrón View Helper para las páginas JSP.

Composite viewUn objeto vista que está compuesto de otros objetos vista. Por ejemplo, una página JSP que incluye otras páginas JSP y HTML usando la directiva include o el action include es un patrón Composite View.

Service To Worker

Es como el patrón de diseño MVC con el Controlador actuando como Front Controller pero con una cosa importante: aquí el Dispatcher (el cual es parte del Front Controller) usa View Helpers a gran escala y ayuda en el manejo de la vista.

Dispatcher View

Es como el patrón de diseño MVC con el controlador actuando como Front Controller pero con un asunto importante: aquí el Dispatcher (el cual es parte del Front Controller) no usa View Helpers y realiza muy poco trabajo en el manejo de la vista. El manejo de la vista es manejado por los mismos componentes de la Vista.

Capa de Negocio

Business Delegate

Un objeto que reside en la capa de presentación y en beneficio de los otros componentes de la capa de presentación llama a métodos remotos de los objetos de la capa de negocios.

Value Object/ Data Transfer Object/ Replicate Object

Un objeto serializable para la transferencia de datos sobre la red.

Session Façade/ Session Entity Façade/ Distributed Façade

El uso de un bean de sesion como una fachada (facade) para encapsular la complejidad de las interacciones entre los objetos de negocio y participantes en un flujo de trabajo. El Session Façade maneja los objetos de negocio y proporciona un servicio de acceso uniforme a los clientes.

Aggregate Entity Un bean entidad que es construido o es agregado a otros beans de entidad.

Value Object Assembler

Un objeto que reside en la capa de negocios y crea Value Objets cuando es requerido.

Value List Handler/ Page-by-Page Iterator/ Paged List

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

Service Locator

Consiste en utilizar un objeto Service Locutor para abstraer toda la utilización JNDI y para ocultar las complejidades de la creación del contexto inicial, de búsqueda de objetos home EJB y recreación de objetos EJB. Varios clientes pueden reutilizar el objeto Service Locutor para reducir la complejidad del código, proporcionando un punto de control.

Page 5: Patrones de Diseño (Capa de Datos)

Capa de Integración

Data Access Object Service Activator

Consiste en utilizar un objeto de acceso a datos para abstraer y encapsular todos los accesos a la fuente de datos. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos.

Service Activator

Se utiliza para recibir peticiones y mensajes asíncronos de los clientes. Cuando se recibe un mensaje, el Service Activator localiza e invoca a los métodos de los componentes de negocio necesarios para cumplir la petición de forma asíncrona.

Plantilla de Patrón

Los patrones J2EE se han estructurado de acuerdo a una plantilla de patrón definida. Cada sección de la plantilla de patrón contribuye a entender el patrón particular. También observarás que se ha intentado dar un nombre de patrón descriptivo a cada patrón J2EE. Aunque es dificil acompasar un patrón singular con su nombre, se ha intentado que los nombres de patrón proporcionen suficiente información sobre la función del patrón.

Se ha adoptado una plantilla de patrón que consta de las siguientes secciones:

Contexto: Conjunto de entornos bajo los cuales existe el patrón.

Problema: Describe los problemas de diseño que se ha encontrado el desarrollador.

Causas: Lista los razones y motivos que afectan al problema y la solución. La lista de causas ilumina las razones por las que uno podría haber elegido utilizar el patrón y proporciona una justificación de su uso.

Solución: Describe brevemente la solución y sus elementos en más detalle. La sección de la solución contiene dos sub-secciones:

o Estructura: Utiliza diagramas de clases UML para mostrar la estructura básica de la solución. Los diagramas de secuencias UML de esta sección presentan los mecanismos dinámicos de la solución. Hay una explicación detalladas de los participantes y las colaboraciones.

o Estrategias: Describe diferentes formas en las que se podría implementar el patrón.

Consecuencias: Aquí se describen las compensaciones del patrón, esta sección se enfoca en los resultados de la utilización de un patrón en particular o de su estrategia, y anota los pros y los contras que podrían resultar de la aplicación del patrón.

Patrones Relacionados: Esta sección lista otros patrones relevantes en el catálogo de patrones J2EE u otros recursos externos, como los patrones de diseño GoF. Por cada patrón relacionado, hay una breve descripción de su relación con el patrón que se está describiendo.

Service Activator

Contexto

Los beans enterprise y otros servicios de negocio necesitan una forma de activarse asíncronamente.

Page 6: Patrones de Diseño (Capa de Datos)

Problema

Cuando un cliente necesita acceder a un bean enteprise, primero busca el objeto home del bean. Luego el cliente le pide a ese objeto home que le proporcione una referencia remota al bean enterprise requerido. Entonces el cliente invoca a los métodos de negocio sobre la referencia remota para acceder a los servicios del bean enterpise. Estas llamadas a métodos, así como las búsquedas y las llamdas a métodos remotos, son síncronos. El cliente tiene que esperar hasta que esos metodos retornan.

Otro factor a considerar es el ciclo de vida de un bean enterprise. La especificación EJB permite que el contenedor pasivice un bean enterprise a un almacenamiento intermedio. Como resultado, el contenedor EJB no tiene un mecanismo mediante el cual poder proporcionar un servicio estilo-proceso para mantener un bean enterprise constantemente activado y en estado listo. Como el cliente debe interactúar con el bean enterprise utilizando su interface remoto, incluso si el bean está en estado activado en el contenedor, el cliente áun necesita obtener su interface remoto mediante un proceso de búsqueda y todavía actúa con el bean de forma síncrona.

Si una aplicación necesita procesamiento síncrono para sus componentes de negocio del lado del servidor, entonces los beans enterprise son una opción apropiada. Algunas aplicaciones cliente podrían requerir este tipo de procesamiento porque los clientes no necesitan esperar o no tienen tiempo para esperar a que se complete el procesamiento. En caso donde la aplicación necesita una forma de procesamiento asíncrono, los beans enterpise no ofrecen esta capacidad en implementaciones anteriores a la especificación EJB 2.0.

La especificación EJB 2.0 proporciona integración introduciendo el bean dirigido-a-mensaje, que es un tipo especial de bean de sesión sin estado que ofrece capacidades de invocación asíncrona. Sin embargo, la nueva especificación no ofrece invocación asíncrona para otros tipos de beans enterprise, como los beans con estado o de entidad.

En general, un servicio de negocio como un bean de sesión o de entidad sólo proporciona procesamiento síncrono y esto representa un reto para implemenetar procesamiento asíncrono.

Causas

Los beans enterprise se exponen a sus clientes mediante sus interfaces remotos, que sólo permiten acceso síncrono.

El contenedor maneja los beans enterprise, permitiendo interacciones sólo mediante referencias remotas. El contenedor EJB no permite acceso directo a la implementación del bean y sus métodos. Así, implementar el oyente de mensajes JMS no es factible en un bean enterprise, ya que esto viola la especificación EJB al permitir el acceso directo a la implementación del bean.

Una aplicación necesita proporcionar un marco de mensajería publicar/suscribir o punto-a-punto donde los clientes puedan publicar peticiones a beans enterprise para procesamiento asíncrono.

Los clientes necesitan capacidades de procesamiento asíncrono en los beans entreprise y otros componentes de negocio que sólo pueden ofrecer acceso síncrono, para que el cliente pueda enviar una petición para su procesamiento sin esperar los resultados.

Los clientes quieren utilizar interfaces de la capa media orientados a mesnajes (MOM) ofrecidos por el API Java Messaging Service (JMS). Estos interfaces no están integrados en los productos servidores EJB que están basados en especificaciones anteriores a la la EJB 2.0.

Una aplicación necesita proporcionar un servicio estilo "criado(daemon)" para que un bean enterprise pueda estar en modo callado hasta que un evento (o un mensaje) dispare su actividad.

Los beans enterprise están sujetos al control de su ciclo de vida por parte del contenedor, lo que incluye la pasivización debido a periodos de inactividad y control de recursos. El cliente tendrá que invocar a un bean enteprise para activarlo de nuevo.

La especificación EJB 2.0 introdujo un bean dirigio-a-mensaje como un bean de sesión sin estado, pero no es posible invocar otros tipos diferentes de beans enteprise de forma asíncrona.

Solución

Page 7: Patrones de Diseño (Capa de Datos)

Utilizar un Service Activator para recibir peticiones y mensajes asíncronos de los clientes. Cuando se recibe un mensaje, el Service Activator localiza e invoca a los métodos de de los componentes de negocio necesarios para cumplir la petición de forma asíncrona.

El ServiceActivator es un oyente JMS y un servicio de delegación que requiere la implementación de un oyente de mensajes JMS. Se puede implementar como un servicio independiente. Los clientes actúan como generadores de mensajes, generando eventos basándose en su actividad.

Cualquier cliente que necesite invocar asíncronamente un servicio de negocio, como un bean enteprise, podría crear y enviar un mensaje al Service Activator. Éste recibe el mensaje y lo analiza para interpretar la petición del cliente. Una vez que se ha analizado y desempaquetado la petición del cliente, el Service Activator identifica y localiza los componentes de servicio de negocio necesarios e invoca a sus métodos de negocio para completar el procesamiento de la petición del cliente de forma asíncrona.

Service Activator opcionalmente podría enviar un reconocimiento al cliente después de que haya completado el procesamiento de la petición. También podría notificar al cliente o a otros servicios si ocurre un fallo durante el procesamiento de la petición.

El Service Activator podría utilizar los servicios de un Service Locator.

Estructura

La siguiente figura representa las relaciones entre clases para el patrón Service Activator:

Participantes y Responsabilidades

La siguiente figura muestra las interacciones entre los distintos participantes en el patrón Service Activator:

Page 8: Patrones de Diseño (Capa de Datos)

EjemploServiceActivatorBean.javapackage drivenbeans;

import javax.ejb.ActivationConfigProperty;import javax.ejb.EJB;import javax.ejb.MessageDriven;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;import sessionbeans.Service1Local;import sessionbeans.Service2Local;

@MessageDriven(mappedName = "jms/server", activationConfig = { @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")})public class ServiceActivatorBean implements MessageListener {

@EJB private Service2Local service2Bean; @EJB private Service1Local service1Bean;

public ServiceActivatorBean() { }

public void onMessage(Message message) {

TextMessage msg = (TextMessage) message; try { String servicio = msg.getText();

Page 9: Patrones de Diseño (Capa de Datos)

if (servicio.equalsIgnoreCase("service1")) service1Bean.metodoDeServicio(); if (servicio.equalsIgnoreCase("service2")) service2Bean.metodoDeServicio();

} catch (JMSException ex) {

}

}}

Service1Bean.javapackage sessionbeans;

import javax.ejb.Stateless;

@Statelesspublic class Service1Bean implements Service1Local {

public void metodoDeServicio() { System.out.println("Se ha invocado el servicio 1"); } }

Service1Local.javapackage sessionbeans;

import javax.ejb.Local;

@Localpublic interface Service1Local {

public void metodoDeServicio();}

Service2Bean.javapackage sessionbeans;

import javax.ejb.Stateless;

@Statelesspublic class Service2Bean implements Service2Local {

public void metodoDeServicio() { System.out.println("Se ha invocado el servicio 2"); } }

Service2Local.javapackage sessionbeans;

import javax.ejb.Local;

@Localpublic interface Service2Local { public void metodoDeServicio(); }Formulario.jsp<html>

Page 10: Patrones de Diseño (Capa de Datos)

<body> <form name="formulario" action="Controlador"> Escriba el nombre del servicio<br/> (service1, service2)<input type="text" name="servicio"> <input type="submit" value="Ejecutar servicio"> </form>

</body></html>

Controlador.javapackage servlets;

import java.io.IOException;import java.io.PrintWriter;import java.util.logging.Level;import java.util.logging.Logger;import javax.annotation.Resource;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageProducer;import javax.jms.Queue;import javax.jms.Session;import javax.jms.TextMessage;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;

public class Controlador extends HttpServlet {

@Resource(name = "jms/server") private Queue server; @Resource(name = "jms/serverFactory") private ConnectionFactory serverFactory;

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { String servicio = request.getParameter("servicio").toString(); sendJMSMessageToServer(servicio); } catch (JMSException ex) { }

}

private Message createJMSMessageForjmsServer(Session session, Object messageData) throws JMSException { // TODO create and populate message to send TextMessage tm = session.createTextMessage(); tm.setText(messageData.toString()); return tm; }

private void sendJMSMessageToServer(Object messageData) throws JMSException { Connection connection = null; Session session = null; try { connection = serverFactory.createConnection(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer messageProducer = session.createProducer(server); messageProducer.send(createJMSMessageForjmsServer(session, messageData));

Page 11: Patrones de Diseño (Capa de Datos)

} finally { if (session != null) { try { session.close(); } catch (JMSException e) { Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Cannot close session", e); } } if (connection != null) { connection.close(); } } }

@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }

@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }}

Data Access Object

Contexto

El acceso a los datos varía dependiendo de la fuente de los datos. El acceso al almacenamiento persistente, como una base de datos, varía en gran medida dependiendo del tipo de almacenamiento (bases de datos relacionales, bases de datos orientadas a objetos, ficheros planos, etc.) y de la implementación del vendedor.

Problema

Muchas aplicaciones de la plataforma J2EE en el mundo real necesitan utilizar datos persistentes en algún momento. Para muchas de ellas, este almacenamiento persistente se implementa utilizando diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder a esos mecanismos de almacenamiento diferentes. Otras aplicaciones podrían necesitar acceder a datos que residen en sistemas diferentes. Por ejemplo, los datos podrían residir en sitemas mainframe, repositorios LDAP, etc. Otro ejemplo es donde los datos los proporcionan servicios a través de sistemas externos como los sistemas de integración negocio-a-negocio (B2B), servicios de tarjetas de crédito, etc.

Normalmente, las aplicaciones utilizan componentes distribuidos y compartidos como los beans de entidad para representar los datos persistentes. Se considera que una aplicación emplea consistencia manejada por el bean (BMP) cuando sus beans de entidad acceden explícitamente al almacenamiento persistente -- el bean de entidad incluye código para hacer esto. Una aplicación con requerimientos sencillos podría por lo tanto utilizar beans de entidad en lugar de beans de sesión o servlets para acceder al almacenamiento persistente y recuperar o modificar los datos. O, la aplicación podría usar beans de entidad con persistencia manejada por el contenedor, y así dejar que el contenedor maneje los detalles de las transaciones y de la persistencia.

Las aplicaciones pueden utilizar el API JDBC para acceder a los datos en un sistema de control de bases de datos relacionales (RDBMS). Este API permite una forma estándar de acceder y manipular datos en un almacenamineto persistente, como una base de datos ralacional. El API JDBC permite a las aplicaciones J2EE utilizar sentencias SQL, que son el método estándar para acceder a tablas RDBMS. Sin embargo,

Page 12: Patrones de Diseño (Capa de Datos)

incluso dentro de un entorno RDBMS, la síntaxis y formatos actuales de las sentencias SQL podrían variar dependiendo de la propia base de datos en particular.

Incluso hay una mayor variación con diferentes tipos de almacenamientos persistentes. Los mecanimos de acceso, los APIs soportados, y sus características varian entre los diferentes tipos de almacenamientos persistentes, como bases de datos relacionales, bases de datos orientadas a objetos, ficheros planos, etc. Las aplicaciones que necesitan acceder a datos de un sistema legal o un sistema dispar (como un mainframe o un servicio B2B) se ven obligados a utilizar APIs que podrían ser propietarios. Dichas fuentes de datos dispares ofrecen retos a la aplicación y potencialmente pueden crear una dependencia directa entre el código de la aplicación y el código de acceso a los datos. Cuando los componentes de negocio -- beans de entidad, beans de sesión e incluso componentes de presentación como servlets y beans de apoyo para páginas JSP -- necesitan acceder a una fuente de datos, pueden utilizar el API apropiado para conseguir la conectividad y manipular la fuente de datos. Pero introducir el código de conectividad y de acceso a datos dentro de estos componentes genera un fuerte acoplamiento entre los componentes y la implementación de la fuente de datos. Dichas dependencias de código en los componentes hace difícil y tedioso migrar la aplicación de un tipo de fuente de datos a otro. Cuando cambia la fuente de datos, también deben cambiar los componentes para manejar el nuevo tipo de fuente de datos.

Causas

Los componentes como los beans de entidad controlados por el bean, los beans de sesión, los servlets, y otros objetos como beans de apoyo para páginas JSP necesitan recuperar y almacenar información desde almacenamientos persistentes y otras fuentes de datos como sistemas legales, B2B, LDAP, etc.

Los APIs para almacenamiento persistente varían dependiendo del vendedor del producto. Otras fuentes de datos podrían tener APIS que no son estándar y/o propietarios. Estos APIs y sus capacidades también varían dependiendo del tipo de almacenamiento -- bases de datos relacionales, bases de datos orientadas a objetos, documentos XML, ficheros planos, etc. Hay una falta de APIs uniformes para corregir los requrimientos de acceso a sistemas tan dispares.

Los componentes normalmente utilizan APIs propietarios para acceder a sistemas externos y/o legales para recuperar y almacenar datos.

La portabilidad de los componentes se ve afectada directamente cuando se incluyen APIs y mecanismos de acceso específicos.

Los componentes necesitan ser transparentes al almacenamiento persistente real o la implementación de la fuente de datos para proporcionar una migración sencilla a diferentes productos, diferentes tipos de almacenamiento y diferentes 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. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos.

El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos. Esta fuente de datos puede ser un almacenamiento persistente como una RDMBS, un servicio externo como un intercambio B2B, un repositorio LDAP, o un servicio de negocios al que se accede mediante CORBA Internet Inter-ORB Protocol (IIOP) o sockets de bajo nivel. Los componentes de negocio que tratan con el DAO utilizan un interface simple expuesto por el DAO para sus clientes. El DAO oculta completamente los detalles de implementación de la fuente de datos a sus clientes. Como el interface expuesto por el DAO no cambia cuando cambia la implementación de la fuente de datos subyacente, este patrón permite al DAO adaptarse a diferentes esquemas de almacenamiento sin que esto afecte a sus clientes o componentes de engocio. Esencialmente, el DAO actúa como un adaptador entre el componente y la fuente de datos.

Estructura

La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrón DAO:

Page 13: Patrones de Diseño (Capa de Datos)

Participantes y Responsabilidades

La siguiente figura muestra el diagrama de secuecnia de la interacción entre los distintos participantes en este patrón:

Page 14: Patrones de Diseño (Capa de Datos)

Ejemplo

Cliente.java

package beans;

public class Cliente {

private String nombre; private String apellidos; private String dni;

public String getNombre() { return nombre; }

public void setNombre(String nombre) { this.nombre = nombre; }

public String getApellidos() { return apellidos; }

public void setApellidos(String apellidos) { this.apellidos = apellidos; }

public String getDni() { return dni; }

public void setDni(String dni) { this.dni = dni; }}

ClienteDAO.javapackage dao;

Page 15: Patrones de Diseño (Capa de Datos)

import beans.Cliente;

public interface ClienteDAO { public void salvar(Cliente c);}

DBClienteDAO.javapackage negocio;

import dao.ClienteDAO;import beans.Cliente;public class DBClienteDAO implements ClienteDAO{

public void salvar(Cliente c) { System.out.println("Registro Salvado a Base de Datos"); //Este método invoca a JDBC nativo para lanzar el insert //contra la base de datos }

}

FileClienteDAO.javapackage negocio;

import beans.Cliente;import dao.ClienteDAO;

public class FileClienteDAO implements ClienteDAO{

public void salvar(Cliente c) { System.out.println("Registro salvado a fichero"); }

}

Controlador.javapackage servlets;

import beans.Cliente;import dao.ClienteDAO;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import negocio.DBClienteDAO;import negocio.FileClienteDAO;

public class Controlador extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { String nombre = request.getParameter("nombre"); String apellidos = request.getParameter("apellidos"); String dni = request.getParameter("dni"); Cliente c = new Cliente(); c.setNombre(nombre); c.setApellidos(apellidos);

Page 16: Patrones de Diseño (Capa de Datos)

c.setDni(dni); ClienteDAO clienteDAO = new FileClienteDAO(); clienteDAO.salvar(c); } finally { out.close(); } }

@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }

@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }

@Override public String getServletInfo() { return "Short description"; }

}

Formulario.jsp<html> <body> <form name="formulario" action="Controlador"> Nombre:<input type="text" name="nombre"/><br/> Apellidos:<input type="text" name="apellidos"/><br/> dni:<input type="dni" name="dni"/><br/> <input type="submit" value="Guardar Datos"/> </form> </body></html>