Вы находитесь на странице: 1из 122

UNIVERSIDAD NACIONAL DEL SANTA

FACULTAD DE INGENIERA

E.A.P. SISTEMAS E INFORMATICA

TEMA:
REQUERIMIENTOS Y PATRONES

CURSO:
ING. DE SOFTWARE

PROFESOR:
CAMILO SUAREZ

INTEGRANTES:

CAMPOS AMAYA LEO

MORENO SAAVEDRA MARCO

CHONG QUISPE ERNESTO

VARGAS LOPEZ JEAN

VELARDE ZIMIC ANDREE

AO:
2016

Requerimientos y Patrones

1. Requerimientos

1.1.

Introduccin

Entender los requerimientos de un problema es una de las tareas


ms difciles que enfrenta el ingeniero de software.

Cuando se piensa por primera vez, no parece tan difcil


desarrollar un entendimiento claro de los requerimientos.
Despus de todo, acaso no sabe el cliente lo que se necesita?
No deberan tener los usuarios finales una buena comprensin
de las caractersticas y funciones que le darn un beneficio?

Sobre las prcticas eficaces respecto de los requerimientos,


alguien escribi lo siguiente:

Es la peor de las pesadillas. Un cliente entra a la oficina, toma


asiento, lo mira a uno fijamente a los ojos y dice: S que cree
que entiende lo que digo, pero lo que usted no entiende es que lo
que digo no es lo que quiero decir..

1.2.

Conceptos de obtencin de requerimientos

1.2.1. Requerimientos funcionales


Los requerimientos funcionales son declaraciones de los servicios
que proveer el sistema, de la manera en que ste reaccionar a
entradas particulares. En algunos casos, los requerimientos
funcionales de los sistemas tambin declaran explcitamente lo
que el sistema no debe hacer.
Muchos de los problemas de la ingeniera de software provienen
de la imprecisin en la especificacin de requerimientos. Para un
desarrollador de sistemas es natural dar interpretaciones de un
requerimiento ambiguo con el fin de simplificar su
implementacin. Sin embargo, a menudo no es lo que el cliente
desea. Se tienen que estipular nuevos requerimientos y se deben
hacer cambios al sistema, retrasando la entrega de ste e
incrementando el costo.
En principio, la especificacin de requerimientos funcionales de
un sistema debe estar completa y ser consistente. La complecin
significa que todos los servicios solicitados por el usuario estn
definidos. La consistencia significa que los requerimientos no
tienen definiciones contradictorias.
En la prctica, para sistemas grandes y complejos, es imposible
cumplir los requerimientos de consistencia y complecin. La razn
de esto se debe parcialmente a la complejidad inherente del
sistema y parcialmente a que los diferentes puntos de vista tienen
necesidades inconsistentes. Estas inconsistencias son obvias
cuando los requerimientos se especifican por primera vez. Los
problemas emergen despus de un anlisis profundo. Una vez
que stos se hayan descubierto en las diferentes revisiones o en
las fases posteriores del ciclo de vida, se deben corregir en el documento
de requerimientos.

1.2.2. Requerimientos no funcionales y seudo-requerimientos

o REQUERIMIENTOS NO FUNCIONALES
Son aquellos requerimientos que no se refieren directamente a
las funciones especficas que entrega el sistema, sino a las
propiedades emergentes de ste como la fiabilidad, la respuesta
en el tiempo y la capacidad de almacenamiento. De forma
alternativa, definen las restricciones del sistema como la
capacidad de los dispositivos de entrada/salida y la
representacin de datos que se utiliza en la interface del sistema.
Los requerimientos no funcionales surgen de la necesidad del
usuario, debido a las restricciones en el presupuesto, a las
polticas de la organizacin, a la necesidad de interoperabilidad
con otros sistemas de software o hardware o a factores externos
como los reglamentos de seguridad, las polticas de privacidad,
entre otros.

o SEUDO-REQUERIMIENTOS

Son requerimientos impuestos por el cliente que restrieguen la


implementacin del sistema.

Ejemplos

Lenguaje de implementacin.
Plataforma en que el sistema debe ser implementado.
Requerimientos del proceso y documentacin.

1.2.3. Niveles de descripcin

o Divisin del trabajo.

Este conjunto de casos de uso describe tos procesos de trabajo


de tos usuarios que son relevantes para el sistema. Tambin se
describe la parte del proceso soportada por el sistema, pero el
meollo est en la definicin de las fronteras entre los usuarios y el
sistema.
o Funciones del sistema especficas de la aplicacin.

Este conjunto de casos de uso describe las funciones


proporcionadas por el sistema que estn relacionadas con el
dominio de aplicacin.
o Funciones del sistema especficas del trabajo.

Este conjunto de casos de uso describe las funciones de apoyo


del sistema que no estn relacionadas con el dominio de
aplicacin. stas incluyen funciones para administracin de
archivos, funciones de agolpamiento, funciones para deshacer,
etc. Estos casos de uso se extendern durante el diseo del
sistema cuando estemos discutiendo condiciones de frontera
conocidas, como la inicializacin del sistema, el apagado y las
polticas para el manejo de excepciones.
o Dilogo.

Este conjunto de casos de uso describe las interacciones entre


los usuarios y la interfaz de usuario del sistema. El enfoque est
en el diseo de la resolucin del flujo de control y asuntos de
disposicin.

1.2.4. Correccin, suficiencia, consistencia, claridad y realismo

o Los requerimientos se validan en forma continua con el cliente y


el usuario. La validacin es un paso crtico en el proceso de
desarrollo, tomando en cuenta que tanto el cliente como el
desarrollador dependen de la especificacin del sistema. La
validacin de requerimientos involucra la revisin para ver si la
especificacin es correcta, completa, consistente, realista y no es
ambigua. Una especificacin es correcta si representa la visin
del cliente del sistema (es decir, todo lo que hay en el modelo de

requerimientos representa con precisin un aspecto del sistema).


Es completa si se describen todos los escenarios posibles que

hay en el sistema, incluyendo el comportamiento excepcional (es


decir, en el modelo de requerimientos estn representados todos
los aspectos del sistema). La especificacin del sistema es
consistente si no se contradice a s misma. La especificacin del
sistema no es ambigua si est definido exactamente un sistema
(es decir, no es posible interpretar la especificacin en dos o ms
formas diferentes). Por ltimo, es realista si el sistema puede
implementarse dentro de esas restricciones.

1.2.5. Verificabilidad y rastreabilidad

o Dos propiedades deseables de una especificacin del sistema


son que sea verificable y ras- treable. La especificacin es
verificable si, una vez que se construye el sistema, se puede
disear una prueba repetible para demostrar que el sistema
satisface los requerimientos. Por ejemplo, una falla de tiempo
medio durante cien aos para el RelojSat sera difcil de lograr
(suponiendo, en primer lugar, que fuera realista). Los siguientes
requerimientos son ejemplos adicionales de requerimientos no
verificables:

El producto debe tener una buena interfaz de usuario (no


se define buena).

El producto debe estar libre de errores (se requieren


muchos recursos para determinarlo).

El producto debe responder al usuario en menos de un


segundo en la mayora de los casos (no se define en la
mayora de los casos).

Una especificacin del sistema es rastreable si cada funcin del


sistema puede rastrearse hasta su conjunto de requerimientos

correspondiente. La rastreabilidad no es una restriccin en el


contenido de la especificacin sino, ms bien, en su organizacin.
La rastreabilidad facilita el desarrollo de pruebas y la validacin
sistemtica del diseo contra los requerimientos.
1.2.6. Ingeniera a partir de cero (greenfield), reingeniera e
ingeniera de interfaz

o Greenfield

En la ingeniera a partir de cero (greenfield) el desarrollo


comienza sin nada, no existe sistema anterior y los
requerimientos se extraen de los usuarios y del cliente. Un
proyecto de ingeniera a partir de cero se activa por una
necesidad del usuario o por la creacin de un nuevo mercado. El
RelojSat es un proyecto de ingeniera a partir de cero.
o Reingeniera

Un proyecto de reingeniera es el rediseo y reimplementacin de


un sistema existente activado por los coordinadores de tecnologa
o por nuevo flujo de informacin [Hammer y Champy, 1993]. A
veces se ampla la funcionalidad del nuevo sistema, pero el
propsito inicial del sistema sigue siendo el mismo. Los
requerimientos del nuevo sistema se extraen de un sistema
existente.

o Ingeniera de Interfaz

Este tipo de proyecto es un proyecto de reingeniera en el cual el


sistema heredado no puede descartarse sin entraar altos costos.
En esta seccin examinamos la manera en que se realiza la
obtencin de requerimientos en estas tres situaciones

1.3.

Actividades para la obtencin de Requerimientos

1.3.1. Identificacin de los actores

Los actores representan entidades externas que interactan con


el sistema. Un actor puede ser un sistema humano o uno externo.
En el ejemplo RelojSat, el propietario del reloj, los satlites GPS y
el dispositivo serial WebificarReloj, son actores (vea la figura 4-3).
Todos ellos interactan e intercambian informacin con el
RelojSat. Sin embargo, observe que todos ellos tienen
interacciones especficas con el RelojSat: el propietario del reloj lo
porta y observa, el reloj rastrea la seal de tos satlites GPS y
WebificarReloj transfiere nuevos datos hacia el reloj. Los actores
definen clases de funcionalidad.

Esto sirve para definir las fronteras del sistema y para encontrar
todas las perspectivas desde las cuales los desarrolladores
necesitan considerarlo. Cuando el sistema se despliega en una
organizacin existente (como una compaa), por lo general ya
existen la mayora de los actores antes de que se desarrolle el
sistema y corresponden a los papeles dentro de la organizacin.

1.3.2. Identificacin de escenarios

Un escenario es una descripcin narrativa de lo que la gente


hace y experimenta cuando trata de utilizar sistemas y
aplicaciones de computadora [Carroll, 1995]. Un escenario es

una descripcin concreta, enfocada e informal de una sola


caracterstica del sistema desde el punto de vista de un solo
actor. El uso de escenarios para la obtencin de requerimientos
es una desviacin conceptual con respecto a las
representaciones tradicionales que son genricas y abstractas.
Las representaciones tradicionales se centran en el sistema y no
en el trabajo al cual da apoyo el sistema. Por ltimo, su enfoque
es la suficiencia, consistencia y precisin, mientras que los
escenarios son abiertos e informales. Un enfoque basado en
escenarios no puede reemplazar por completo (y no se pretende
que lo haga) a los enfoques tradicionales. Sin embargo, mejora la
obtencin de requerimientos proporcionando una herramienta que
es comprensible con facilidad para usuarios y clientes.

1.3.3. Identificacin de casos de uso

Un escenario es una instancia de una cado de uso, esto es, un


caso de uso especifica todos los escenarios posibles para una
parte de funcionalidad dad, Un caso de uso es indicado por un
actor.

Despus de haber sido iniciado, un caso de uso tambin puede


interactuar con otros actores. Un caso de uso representa un flujo
de eventos completo a travs del sistema, en el sentido de que
describe una serie de interacciones relacionadas que resultan de
la iniciacin del caso de uso.

1.3.4. Refinamiento de los casos de uso

El uso de escenarios y casos de uso para definir la funcionalidad


del sistema ayuda en la creacin de requerimientos que son

validados por el usuario al inicio del desarrollo. Conforme


empiezan el diseo y la implementacin del sistema se
incrementa el costo de los cambios a la especificacin del sistema
y la adicin de nuevas funcionalidades no previstas. Aunque los
requerimientos cambian hasta cerca del final del desarrollo, los
desarrolladores y usuarios deben esforzarse para manejar desde
el principio la mayora de los requerimientos. Esto implica muchos
cambios y experimentacin durante la obtencin de
requerimientos. Observe que muchos casos de uso se escriben
varias veces, otros se refinan mucho y otros, incluso, se eliminan
por completo. Para ahorrar tiempo se puede realizar mucho
trabajo de exploracin usando escenarios y maquetas de interfaz.
Se puede usar la siguiente heurstica para la escritura de
escenarios y casos de uso.

1.3.5. Identificacin de las relaciones entre actores y casos de


uso

o Relaciones de comunicacin entre actores y casos de uso

Las relaciones de comunicacin entre actores y casos de uso


representan el flujo de informacin durante el caso de uso. Se
debe distinguir entre el actor que inicia el caso de uso y los
dems actores con los que se comunica el caso de uso. Por lo
tanto, el control de acceso (es decir, cul actor tiene acceso a
cul funcionalidad de clase) puede representarse a este nivel. Las
relaciones entre actores y casos de uso se identifican cuando se
identifican los casos de uso.

o Relaciones extendidas entre casos de uso

Un caso de uso extiende otro caso de uso si el caso de uso


extendido puede incluir el comportamiento de la extensin bajo
determinadas condiciones.

o Relaciones de inclusin entre casos de uso

Las redundancias entre casos de uso pueden factorizarse usando


relaciones de inclusin. Supongamos, por ejemplo, que un D
espachador necesita consultar el plano de la ciudad cuando abre
un incidente (por ejemplo, para verificar cules reas tienen
riesgo durante un incendio) y cuando asigna recursos (por
ejemplo, para saber cules recursos estn ms cercanos al
incidente).
o Relaciones extendidas frente a inclusin

Las construcciones de inclusin y extendidas son similares, y al


principio puede ser que no le quede claro al desarrollador cundo
hay que usar cada una de ellas [Jacobson et al., 1992]. La
principal distincin entre estas construcciones es la direccin de
la relacin. En el caso de una relacin de inclusin, las
condiciones bajo las cuales se inicia el caso de uso estn
descritas en el caso de uso iniciador como un evento en el flujo
de eventos.

1.3.6. Identificacin inicial de los objetos de anlisis

Uno de los primeros obstculos que encuentran los


desarrolladores y los usuarios cuando colaboran es la
terminologa diferente. Se produce una falta de comprensin por
usar los mismos trminos en contextos diferentes y con diferente

significado. Aunque los desarrolladores con el tiempo aprenden la


terminologa de los usuarios, es probable que vuelvan a encontrar
este problema cuando aadan nuevos desarrolladores al
proyecto. Una vez que se han consolidado los casos de uso, los
desarrolladores identifican los objetos participantes en cada caso
de uso. Los objetos participantes corresponden a los conceptos
principales del dominio de aplicacin. Los desarrolladores los
identifican, nombran y describen sin ambigedad, y los renen en
un glosario. Este glosario se incluye en la identificacin del
sistema y ms adelante en los manuales de usuario. Los
desarrolladores mantienen actualizado este glosario conforme
evoluciona la especificacin del sistema. Son muchos los
beneficios del glosario: los nuevos desarrolladores quedan
expuestos a un conjunto de definiciones consistentes, un solo
trmino se usa para cada contexto (en vez de un trmino del
desarrollador y un trmino del usuario) y cada trmino tiene un
significado oficial preciso y claro.

1.3.7. Identificacin de requerimientos no funcionales

Los requerimientos no funcionales describen aspectos del sistema visibles para


el usuario que no estn relacionados en forma directa con el comportamiento
funcional del sistema. Los requerimientos no funcionales abarcan varios
asuntos, desde la apariencia de la interfaz de usuario hasta los requerimientos
de tiempo de respuesta y las cuestiones de seguridad. Los requerimientos no
funcionales se definen al mismo tiempo que los funcionales, debido a que
tienen mucho impacto en el desarrollo y costo del sistema. Se pueden obtener
investigando los siguientes temas:

Interfaz de usuario y factores humanos

Documentacin

Consideraciones de hardware

1.4.

Caractersticas de desempeo

Manejo de errores y condiciones externas

Asuntos de calidad

Modificaciones al sistema

Ambiente Fsico

Ambiente Fsico

Cuestiones de Seguridad

Cuestiones de recursos.

Administracin de la obtencin de Requerimientos

En la seccin anterior describimos las cuestiones tcnicas del modelado de un


sistema desde el punto de vista de tos casos de uso. Sin embargo, el modelado
de casos de uso no constituye, por s mismo, la obtencin de requerimientos.
Aun despus de que se convierten en expertos modeladores de casos de uso,
los desarrolladores todava necesitan obtener requerimientos de los usuarios y
llegar a un acuerdo con el cliente. En esta seccin describimos mtodos para la
obtencin de informacin de los usuarios y la negociacin de un acuerdo con
un cliente.

1.4.1. Obtencin de informacin de los usuarios


El anlisis de tareas se basa en la suposicin de que es poco eficiente pedir a tos usuarios que
describan lo que hacen y la manera en que lo hacen. Los usuarios, por lo general, no piensan
en forma explcita en la secuencia de tareas que se requieren para realizar su trabajo, ya que
con frecuencia repiten estas tareas muchas veces. Cuando se pregunta a los usuarios la
manera en que realizan su trabajo, describen, en el mejor de los casos, la manera en que se
supone que lo realizan, y esto puede estar muy lejano de la realidad. En consecuencia, el
anlisis de tareas usa la observacin como una alternativa para construir un modelo de tarea
inicial. Este modelo de tarea inicial se refina luego preguntndole a los usuarios por qu
realizan una tarea de determinada forma. Se puede resumir al KAT en 5 pasos.
puede resumir al KAT con los cinco pasos siguientes:

Identificacin de objetos y acciones.


Se identifican los objetos y acciones asociadas con los objetos
usando tcnicas similares a las de la identificacin de objetos en
el anlisis orientado a objetos, como el anlisis de libros de texto,
manuales, reglamentos, reportes, entrevistas con quien realiza la
tarea y la observacin de quien realiza la tarea.

Identificacin de procedimientos

Un procedimiento es un conjunto de acciones, una condicin


previa necesaria para activar el procedimiento y una condicin
posterior. Las acciones pueden estar ordenadas en forma parcial.
Los procedimientos se identifican mediante la redaccin de
escenarios, la observacin de quien realiza la tarea y pidindole a
quien realiza la tarea que seleccione y ordene tarjetas en las que
se escriben acciones individuales.

Identificacin de objetivos y subjetivos

Un objetivo es un estado a lograr para que la tarea sea


satisfactoria. Los objetivos se identifican mediante entrevistas
durante la realizacin de una tarea o despus de ella. Los
subjetivos se identifican descomponiendo los objetivos.

Identificacin del carcter tpico y la importancia.

Cada elemento identificado se califica de acuerdo con la


frecuencia con que se le encuentra y si es necesario para la
realizacin de un objetivo.

Construccin de un modelo de la tarea.

La informacin recopilada antes se generaliza para tomar en


cuenta las caractersticas comunes que hay entre las tareas. Se
relacionan los objetivos, procedimientos y objetos
correspondientes usando una notacin textual o una grfica. Por
ltimo se valida el modelo con quien realiza la tarea.

1.4.2. Negociacin de especificaciones con los clientes

El diseo conjunto de aplicaciones (JAD, por sus siglas en ingls)


es un mtodo de requerimientos desarrollado por IBM a finales de
los setenta. Su efectividad radica en que el trabajo de obtencin
de requerimientos se realiza en una sola sesin de trabajo en la
que participan todos los involucrados. Usuarios, clientes,
desarrolladores y un lder de sesin entrenado se sientan juntos
en un saln para presentar sus puntos de vista, escuchar los
puntos de vista de los dems, negociar y ponerse de acuerdo en
una solucin mutuamente aceptable. El resultado de la sesin de
trabajo, el documento JAD final, es un documento de
especificacin de sistema completo que incluye definiciones de
elementos de datos, flujos de trabajo y pantallas de interfez.
Debido a que el documento final es desarrollado en forma
conjunta por todos los interesados (es decir, los participantes que
no slo tienen un inters en el xito del proyecto sino que tambin
pueden tomar decisiones sustanciales), el documento JAD final
representa un acuerdo entre usuarios, clientes y desarrolladores
y, por lo tanto, minimiza los cambios de requerimientos
posteriores en el proceso de desarrollo.

Definicin del proyecto.

Durante esta actividad el coordinador JAD entrevista a


gerentes y clientes para determinar los objetivos y el
alcance del proyecto. Lo que encuentra en las entrevistas
se recopila en la gua de definicin administrativa. Durante
esta actividad, el coordinador JAD forma un equipo
compuesto por usuarios, clientes y desarrolladores. Estn
representados todos los interesados, y los participantes
tienen la capacidad de tomar decisiones conjuntas.

Investigacin.

Durante esta actividad el coordinador JAD entrevista a los


usuarios presentes y futuros, recopila informacin del
dominio y describe los flujos de trabajo. El coordinador JAD
tambin inicia una lista de asuntos que necesitarn tratarse
durante la reunin. Los resultados principales de la
actividad de investigacin son una agenda de sesin y una
especificacin preliminar que lista el flujo de trabajo y la
informacin del sistema.

Preparacin.

Durante esta actividad el coordinador JAD prepara la


sesin. El coordinador JAD crea un documento de trabajo,
primer borrador del documento final, una agenda para la
sesin y cualquier cantidad de filminas o grficas que
representan la informacin recopilada durante la actividad
de investigacin.

Sesin.
Durante esta actividad el coordinador JAD gua al equipo
para la creacin de la especificacin del sistema. Una

sesin JAD dura de tres a cinco das. El equipo define y se


pone de acuerdo en el flujo de trabajo, los elementos de
datos, las pantallas y los reportes del sistema. Todas las
decisiones se documentan mediante un escribano que
llena formularios JAD.

Documento final.

El coordinador JAD prepara el documento final revisando el


documento de trabajo para que incluya todas las
decisiones tomadas durante la sesin. El documento final
representa una especificacin completa del sistema
acordada durante la sesin. El documento final se
distribuye a los participantes en la sesin para que lo
revisen. Luego los participantes se renen durante una a
dos horas para discutir las revisiones y finalizar el
documento.

1.4.3. Validacin de requerimientos: prueba de utilidad

Las pruebas de utilidad examinan la comprensin que tiene el


usuario del modelo de los casos de uso. Las pruebas de utilidad
encuentran problemas en la especificacin del sistema
permitiendo que los usuarios exploren el sistema o slo parte de
l (por ejemplo, la interfaz de usuario). Las pruebas de utilidad
tambin se interesan en los detalles de la interfaz de usuario,
como la apariencia de la interfaz de usuario, la disposicin
geomtrica de las pantallas y el hardware. Por ejemplo, en el
caso de una computadora que se lleva en el cuerpo, una prueba
de utilidad podra comprobar la habilidad del usuario para darle
comandos al sistema mientras se encuentra en una posicin

difcil, como el caso de un mecnico viendo una pantalla debajo


de un automvil mientras revisa el silenciador del escape. Hay
tres tipos de pruebas de utilidad:

Prueba de escenario.
Durante esta prueba se presenta un escenario visionario
del sistema ante uno o ms usuarios. Los desarrolladores
identifican qu tan rpido pueden comprender tos usuarios
el escenario, con cunta precisin representa su modelo
de trabajo y qu tan positivamente reaccionan a la
descripcin del nuevo sistema. Los escenarios
seleccionados debern ser lo ms realistas y detallados
posible. Una prueba de escenario permite una retroalimentacin rpida y frecuente del usuario. Las pruebas
de escenario pueden realizarse como maquetas en papel o
con un ambiente prototipo simple, el cual con frecuencia es
ms fcil de aprender que el ambiente de programacin
que se usa para el desarrollo. La ventaja de las pruebas de
escenario es que es barato realizarlas y repetirlas. La
desventaja es que el usuario no puede interactuar en forma
directa con el sistema y que los datos son fijos.

Prueba de prototipo.

Durante este tipo de prueba se presenta ante uno o ms


usuarios un fragmento de software que prcticamente
implementa al sistema. Un prototipo vertical implementa un
caso de uso completo a lo largo del sistema y un prototipo
horizontal presenta una interfaz para la mayora de los
casos de uso (propacionando poca o ninguna
funcionalidad). Las ventajas de las pruebas de prototipo
consisten en que proporcionan una vista realista del
sistema ante el usuario y que se pueden implementar tos
prototipos para recolectar datos detallados. Las

desventajas de tos prototipos son los altos costos de


producirlos y modificarlos.

Prueba de producto

Esta prueba es similar a la de prototipo, a excepcin de


que se usa una versin funcional del sistema en vez del
prototipo. Una prueba de producto slo puede

1.4.4. Documentacin de la obtencin de requerimientos

Los resultados de la actividad de obtencin de requerimientos y la


actividad de anlisis se documentan en el documento de anlisis
de requerimientos (RAD, por sus siglas en ingls). Este
documento describe por completo al sistema desde el punto de
vista de los requerimientos funcionales y no funcionales, y sirve
como una base contractual entre el cliente y los desarrolladores.
La audiencia del RAD incluye al cliente, los usuarios, los
administradores del proyecto, los analistas del sistema (es decir,
los desarrolladores que participan en los requerimientos) y los
diseadores del sistema (es decir, los desarrolladores que
participan en el diseo del sistema). La primera parte del
documento, incluyendo los casos de uso y los requerimientos no
funcionales, se escribe durante la obtencin de requerimientos.
La formalizacin de la especificacin en trminos de modelos de
objetos se escribe durante el anlisis. La siguiente es una plantilla
de ejemplo para un RAD:

2. Patrones

2.1.

Patrn Abstract Factory

2.1.1. Definicin

El patrn Abstract Factory nos permite crear, mediante una


interfaz, conjuntos o familias de objetos (denominados productos)
que dependen mutuamente y todo esto sin especificar cul es el
objeto concreto. Este patrn se puede aplicar cuando:
Un sistema debe ser independiente de cmo sus objetos son
creados.
Un sistema debe ser 'configurado' con una cierta familia de
productos.
Se necesita reforzar la nocin de dependencia mutua entre
ciertos objetos.

2.1.2. Esquema

Cliente
La clase que llamar a la factora adecuada ya que necesita crear
uno de los objetos que provee la factora, es decir, Cliente lo que
quiere es obtener una instancia de alguno de los productos
(ProductoA, ProductoB).

AbstractFactory
Es la definicin de la interfaces de las factoras. Debe de proveer un
mtodo para la obtencin de cada objeto que pueda crear.
("crearProductoA()" y "crearProductoB()")

Factoras Concretas
Estas son las diferentes familias de productos. Provee de la instancia
concreta de la que se encarga de crear. De esta forma podemos
tener una factora que cree los elementos grficos para Windows y
otra que los cree para Linux, pudiendo poner fcilmente (creando
una nueva) otra que los cree para MacOS, por ejemplo.

Producto abstracto
Definicin de las interfaces para la familia de productos genricos.
En el diagrama son "ProductoA" y "ProductoB". En un ejemplo de
interfaces grficas podran ser todos los elementos: Botn, Ventana,
Cuadro de Texto, Combo... El cliente trabajar directamente sobre
esta interfaz, que ser implementada por los diferentes productos
concretos.

Producto concreto
Implementacin de los diferentes productos. Podra ser por ejemplo
"BotnWindows" y "BotnLinux". Como ambos implementan "Botn"
el cliente no sabr si est en Windows o Linux, puesto que trabajar
directamente sobre la superclase o interfaz.

2.1.3. Ejemplo General


Supongamos que disponemos de una cadena de pizzeras. Para
crear pizzas disponemos de un mtodo abstracto en la clase
Pizzera que ser implementada por cada subclase de Pizzera.

abstract Pizza crearPizza()

Concretamente se crear una clase Pizzera Zona por cada zona,


por ejemplo la Pizzera de New York sera PizzeriaNewYork y la
de California PizzeraCalifornia que implementarn el mtodo con
los ingredientes de sus zonas.

Las pizzas son diferentes segn las zonas. No es igual la pizza de


New York que la pizza de California. Igualmente, aunque usarn
los mismos ingredientes (tomate, mozzarella...) no los obtendrn
del mismo lugar, cada zona los comprar donde lo tenga ms
cerca. As pues podemos crear un mtodo creador de Pizza que
sea
Pizza(FactoriaIngredientes fi);
Como vemos utilizamos la factora abstracta (no las concretas de
cada zona, como podra ser IngredientesNewYork o
IngredientesCalifornia). Pizza podr obtener los ingredientes de la
factora independientemente de donde sea. Sera fcil crear
nuevas factoras y aadirlas al sistema para crear pizzas con
estos nuevos ingredientes. Efectivamente, en este
ejemplo cliente es Pizza y es independiente de la Factora usada.

El creador de la Pizza ser el encargado de instanciar la factora


concreta, as pues los encargados de instanciar las factoras
concretas sern las pizzeras locales. En PizzeraNewYork

podemos tener el mtodo crearPizza() que realice el siguiente


trabajo:
Pizza crearPizza() {
FactoraIngredientes fi = new IngredientesNewYork();
Pizza pizza = new Pizza(fi); // Uso de la factora
pizza.cortar();
pizza.empaquetar();
return pizza;}
Como conclusin podemos observar que gracias a la factora de
ingredientes crear una nueva zona, por ejemplo una pizzera en
Barcelona, no nos implicara estar modificando el cdigo existente, solo
deberemos extenderlo (uno de los pilares de la Ingeniera del software)
ya crearamos la subclase de Pizzera: PizzeraBarcelona que al
instanciar la factora solo debera escoger la factora de Barcelona.
Obviamente se debera crear la factora de Barcelona que se encargara
de crear los productos obtenidos de Barcelona. As que en ningn
momento modificamos las pizzeras existentes, la superclase pizzera o
las otras factoras o productos, solo creamos nuevas clases.

2.1.4. Ejemplo con acceso a BD

Basada en los patrones Abstract Factory y Factory Method


Pasos:
Definir la interface DAO de nuestros objetos de datos
public interface ClienteDAO {
public Cliente create (String nombre, String nif, String correo, String
usuario, String clave)
throws DAOException;
public Cliente findClienteByUsuario (String usuario) throws
DAOException;
public java.util.Collection findAll () throws DAOException;
public void update (Cliente c) throws DAOException; }

Definir la factora abstracta de objetos DAO:

public abstract class DAOFactoria {


public abstract ClienteDAO getClienteDAO() throws DAOException;
public abstract ProductoDAO getProductoDAO() throws DAOException;
public final static int ACCESS = 1;
...
public static DAOFactoria getDAOFactoria (int tipo) {
switch (tipo) {
case ACCESS:
return new AccessDAOFactoria();
case XML:
}
Implementar la factora concreta:

public class AccessDAOFactoria extends DAOFactoria{


...
public ClienteDAO getClienteDAO() {
return (ClienteDAO) new AccessClienteDAO(ds); } }
Simplemente instancia objetos DAO concretos.
Implementar las clases DAO concretas:

import java.sql.*;
public class AccessClienteDAO implements ClienteDAO {
...
public Cliente create (String nombre, String nif, String correo, String
usuario, String clave) throws DAOException {
Connection con = null;
try {
con = ds.getConnection();
Statement stmt = con.createStatement();
stmt.executeUpdate(...);
stmt.close(); con.close();
Cliente c = new Cliente();
c.setNombre(nombre);
... return c; }

2.2.

Patrn Estrategy

2.2.1. Definicin

El patrn Estrategia (Strategy) es un patrn de diseo para el


desarrollo de software. Se clasifica como patrn de
comportamiento porque determina cmo se debe realizar el
intercambio de mensajes entre diferentes objetos para resolver
una tarea. El patrn estrategia permite mantener un conjunto
de algoritmos de entre los cuales el objeto cliente puede elegir
aquel que le conviene e intercambiarlo dinmicamente segn
sus necesidades.

2.2.2. Esquema

Las clases y objetos que participan en este modelo son:


Strategy
o Declara una interfaz comn para todos los algoritmos
compatibles. El Contexutiliza esta interfaz para llamar al algoritmo
definido por un ConcreteStrategy
ConcreteStrategy
o Implementa el algoritmo utilizando la interfaz de Strategy
Context
o Est configurado con un objeto ConcreteStrategy

o Mantiene una referencia a un objeto de Strategy


o Puede definir una interfaz que le permite acceder a sus
datos Strategy.

2.2.3. Ejemplo General


public class Main {
public static void main(String args[])
{
//Usamos la estrategia A
Strategy estrategia_inicial = new StrategyA();
Context context = new Context(estrategia_inicial);
context.some_method();

//Decidimos usar la estrategia B


Strategy estrategia2 = new StrategyB();
context.setStrategy(estrategia2);
context.some_method();

//Finalmente,usamos de nuevo la estrategia A


context.setStrategy(estrategia_inicial);
context.some_method();

/** Salida:
* Estrategia A
* Estrategia B
* Estrategia A

**/
}
}

public class Context {


Strategy c;

public Context( Strategy c )


{
this.c = c;
}

public void setStrategy(Strategy c) {


this.c = c;
}

//Mtodo de estrategia 'c'


public void some_method()
{
c.behaviour();
}
}

public Interface Strategy{


public void behaviour();
}

public class StrategyA implements Strategy{


@Override
public void behaviour() {
System.out.println("Estrategia A");
}
}

public class StrategyB implements Strategy{


@Override
public void behaviour() {
System.out.println("Estrategia B");
}
}

2.2.4. Ejemplo con acceso a BD

Aplicado a un ejemplo en PHP, imaginemos que queremos conectarnos a una


base de datos, pero no sabemos si va a ser Oracle o MySQL (podra haber
tantas como quisiramos). El usuario elegir en un formulario las opciones de
bases de datos que se especifiquen en un desplegable, pasando por POST el
parmetro dbms.
/* Fichero Conexion.php */
// Estrategia: Interfaz
interface Conexion {
public function conectar($usuario, $clave) { }
}

/* Fichero ConexionOracle.php */
// Estrategia concreta: Oracle
class ConexionOracle implements Conexion {
public function conectar($usuario, $clave) {
return oci_connect($usuario, $clave);
}
}

/* Fichero ConexionMysql.php */
// Estrategia concreta: MySQL
class ConexionMysql implements Conexion {
public function conectar($usuario, $clave) {
return mysql_connect("localhost", $usuario, $clave);
}
}

/* Fichero index.php */
// Contexto
/*
* $_POST['dbms'] proviene de un cuadro desplegable (option select) en
que se da a escoger entre oracle y mysql.
* ucfirst() pone en mayscula la primera letra
*/
$conector = "Conexion" . ucfirst($_POST['dbms']);
$instancia = new $conector;

try {
$recurso = $instancia->conectar($_POST['usuario'],
$_POST['clave']);
} catch (Exception $e) {
echo "Lo sentimos, pero por algn motivo la conexin ha fallado.";
}

2.3.

Patrn Factory Method

2.3.1. Definicin

En diseo de software, el patrn de diseo Factory


Method consiste en utilizar una clase constructora (al estilo del
Abstract Factory) abstracta con unos cuantos mtodos
definidos y otro(s) abstracto(s): el dedicado a la construccin
de objetos de un subtipo de un tipo determinado. Es una
simplificacin del Abstract Factory, en la que la clase
abstracta tiene mtodos concretos que usan algunos de los
abstractos; segn usemos una u otra hija de esta clase
abstracta, tendremos uno u otro comportamiento.

2.3.2. Esquema

Las clases principales en este patrn son el creador y


el producto. El creador necesita crear instancias de productos,
pero el tipo concreto de producto no debe ser forzado en las
subclases del creador, porque las posibles subclases del
creador deben poder especificar subclases del producto para
utilizar.

2.3.3. Ejemplo General

abstract class Creator{


// Definimos mtodo abstracto
public abstract Product factoryMethod();
}
Ahora definimos el creador concreto:

public class ConcreteCreator extends Creator{


public Product factoryMethod() {
return new ConcreteProduct();
}
}
Definimos el producto y su implementacin concreta:

public interface Product{

public void operacion();


}

public class ConcreteProduct implements Product{


public void operacion(){
System.out.println("Una operacin de este producto");
}
}
Ejemplo de uso:

public static void main(String args[]){


Creator aCreator;
aCreator = new ConcreteCreator();
Product producto = aCreator.factoryMethod();
producto.operacion();
}
2.3.4. Ejemplo con acceso a BD
Basada en los patrones Abstract Factory y Factory Method
Pasos:
Definir la interface DAO de nuestros objetos de datos
public interface ClienteDAO {
public Cliente create (String nombre, String nif, String correo, String
usuario, String clave)
throws DAOException;
public Cliente findClienteByUsuario (String usuario) throws
DAOException;
public java.util.Collection findAll () throws DAOException;
public void update (Cliente c) throws DAOException; }

Definir la factora abstracta de objetos DAO:

public abstract class DAOFactoria {


public abstract ClienteDAO getClienteDAO() throws DAOException;
public abstract ProductoDAO getProductoDAO() throws DAOException;
public final static int ACCESS = 1;
...
public static DAOFactoria getDAOFactoria (int tipo) {
switch (tipo) {
case ACCESS:
return new AccessDAOFactoria();
case XML:
}
Implementar la factora concreta:

public class AccessDAOFactoria extends DAOFactoria{


...
public ClienteDAO getClienteDAO() {
return (ClienteDAO) new AccessClienteDAO(ds); } }
Simplemente instancia objetos DAO concretos.
Implementar las clases DAO concretas:

import java.sql.*;
public class AccessClienteDAO implements ClienteDAO {
...
public Cliente create (String nombre, String nif, String correo, String
usuario, String clave) throws DAOException {
Connection con = null;
try {
con = ds.getConnection();
Statement stmt = con.createStatement();
stmt.executeUpdate(...);
stmt.close(); con.close();
Cliente c = new Cliente();
c.setNombre(nombre);
... return c; }

2.4.

Patrn Prototype

2.4.1. Definicin
El patrn de diseo Prototype (Prototipo), tiene como finalidad
crear nuevos objetos duplicndolos, clonando una instancia
creada previamente.
Este patrn especifica la clase de objetos a crear mediante la
clonacin de un prototipo que es una instancia ya creada. La
clase de los objetos que servirn de prototipo deber incluir en su
interfaz la manera de solicitar una copia, que ser desarrollada
luego por las clases concretas de prototipos.

2.4.2. Esquema

Cliente: Es el encargado de solicitar la creacin de los nuevos


objetos a partir de los prototipos.

Prototipo Concreto: Posee caractersticas concretas que sern


reproducidas para nuevos objetos e implementa una operacin
para clonarse.

Prototipo: Declara una interfaz para clonarse, a la que accede el


cliente.

2.4.3. Ejemplo General


// Los productos deben implementar esta interface
public interface Producto implements Cloneable {
Object clone();
// Aqu van todas las operaciones comunes a los productos que genera la factora
}

// Un ejemplo bsico de producto


public class UnProducto implements Producto {
private int atributo;

public UnProducto(int atributo) {


this.atributo = atributo;
}

public Object clone() {


return new UnProducto(this.atributo);
}

public String toString() {


return ((Integer)atributo).toString();
}
}

// La clase encargada de generar objetos a partir de los prototipos


public class FactoriaPrototipo {

private HashMap mapaObjetos;


private String nombrePorDefecto;

public FactoriaPrototipo() {
mapaObjetos = new HashMap();
// Se incluyen en el mapa todos los productos prototipo
mapaObjetos.put("producto 1", new UnProducto(1));
}

public Object create() {


return create(nombrePorDefecto);
}

public Object create(String nombre) {


nombrePorDefecto = nombre;
Producto objeto = (Producto)mapaObjetos.get(nombre);
return objeto != null ? objeto.clone() : null;
}
}

public class PruebaFactoria {


static public void main(String[] args) {
FactoriaPrototipo factoria = new FactoriaPrototipo();
Producto producto = (Producto) factoria.create("producto 1");
System.out.println ("Este es el objeto creado: " + producto);
}
}

2.4.4. Ejemplo con acceso a BD

public abstract class Shape implements Cloneable


private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object clone() {
Object clone = null;

try {
clone = super.clone();

} catch (CloneNotSupportedException e) {
e.printStackTrace();
}

return clone;
}
}

A continuacin extendemos dicho objeto con nuestras clases que se


diferencian solo en el tipo.

public class Rectangle extends Shape {

public Rectangle(){
type = "Rectangle";
}

@Override
public void draw() {
System.out.println("Insideangle::draw() method.");
}
}
public class Square extends Shape {

public Square(){
type = "Square";
}

@Override
public void draw() {
System.out.println("Insidere::draw() method.");
}
}
public class Circle extends Shape {

public Circle(){
type = "Circle";
}

@Override
public void draw() {
System.out.println("Insidele::draw() method.");
}
}
A continuacin creamos la clase que nos va a proporcionar su cacheo y evitar
crearlos leyendo de la base de datos.

import java.util.Hashtable;

public class ShapeCache {

private static Hashtable shapeMap = new Hashtable();

public static Shape getShape(String shapeId) {


Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}

// for each shape run database query and create shape


// shapeMap.put(shapeKey, shape);
// for example, we are adding three shapes
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1

shapeMap.put(circle.getId(),circle);

Square square = new Square();


square.setId("2

shapeMap.put(square.getId(),square);

Rectangle rectangle = new Rectangle();


rectangle.setId("3

shapeMap.put(rectangle.getId(), rectangle);

}
}
Tan solo nos queda usarlo

public class PrototypePatternDemo {


public static void main(String[] args) {
ShapeCache.loadCache();

Shape clonedShape = (Shape) ShapeCache.getShape("1");


System.out.println("Shape+ clonedShape.getType());

Shape clonedShape2 = (Shape) ShapeCache.getShape("2");


System.out.println("Shape+ clonedShape2.getType());

Shape clonedShape3 = (Shape) ShapeCache.getShape("3");


System.out.println("Shape+ clonedShape3.getType());
}
}
y comprobar la salida en consola

Shape : Circle
Shape : Square
Shape : Rectangle

2.5.

Patrn Singleton

2.5.1. Definicin

Su intencin consiste en garantizar que una clase slo tenga


una instancia y proporcionar un punto de acceso global a ella.

El patrn singleton se implementa creando en nuestra clase


un mtodo que crea una instancia del objeto slo si todava no
existe alguna. Para asegurar que la clase no puede ser
instanciada nuevamente se regula el alcance
del constructor (con modificadores de acceso como protegido o
privado).

La instrumentacin del patrn puede ser delicada en programas


con mltiples hilos de ejecucin. Si dos hilos de
ejecucin intentan crear la instancia al mismo tiempo y esta no
existe todava, slo uno de ellos debe lograr crear el objeto. La
solucin clsica para este problema es utilizar exclusin mutua en
el mtodo de creacin de la clase que implementa el patrn.

2.5.2. Esquema

2.5.3. Ejemplo General

public class Singleton {


private static Singleton INSTANCE = null;

// Private constructor suppresses


private Singleton(){}

// creador sincronizado para protegerse de posibles problemas multi-hilo


// otra prueba para evitar instanciacin mltiple
private synchronized static void createInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}

public static Singleton getInstance() {


if (INSTANCE == null) createInstance();
return INSTANCE;
}
}

2.5.4. Ejemplo con acceso a BD

Crearemos una clase llamada Conexion, y para empezar


declararemos una instancia de sta clase y un constructor de
manera privada:
public class Conexion{
private static Conexion instancia = null;
private Conexion(){

}
}

Ahora, crearemos el punto de acceso a nuestra instancia mediante


un mtodo getInstancia:
public static Conexion getInstancia(){
if(instancia == null){
instancia = new Conexion();
}
return instancia;
}

Para finalizar aadimos una clase que se encargue de tener


almacenada la conexin con la base de datos Mysql y un mtodo
de acceso a dicha clase.
El cdigo final quedara de la siguiente manera:

2.6.

Patrn Adapter

2.6.1. Definicin

Se utiliza para transformar una interfaz en otra, de tal modo que


una clase que no pudiera utilizar la primera, haga uso de ella a
travs de la segunda.

2.6.2. Esquema

Target define la interfaz especfica del dominio que Client usa.

Client colabora con la conformacin de objetos para la


interfaz Target.

Adaptee define una interfaz existente que necesita adaptarse

Adapter adapta la interfaz de Adaptee a la interfaz Target

2.6.3. Ejemplo General

package Structural_patterns;
public class AdapterWrapperPattern {
public static void main(String args[]){
Guitar eGuitar = new ElectricGuitar();
eGuitar.onGuitar();

eGuitar.offGuitar();
Guitar eAGuitar = new ElectricAcousticGuitar();
eAGuitar.onGuitar();
eAGuitar.offGuitar();
}
public abstract class Guitar{
abstract public void onGuitar();
abstract public void offGuitar();
}
public class ElectricGuitar extends Guitar{
public void onGuitar() {
System.out.println("Playing Guitar");
}
public void offGuitar() {
System.out.println("I'm tired to play the guitar");
}
}
/**
* Class to Adapter/Wrapper
*/
public class AcousticGuitar{

public void play(){


System.out.println("Playing Guitar");
}
public void leaveGuitar(){
System.out.println("I'm tired to play the guitar");
}
}

/**
* we Adapter/Wrapper AcousticGuitar into
* ElectricAcousticGuitar to adapt into the GuitarModel
*/
public class ElectricAcousticGuitar extends Guitar{
AcousticGuitar acoustic = new AcousticGuitar();

public void onGuitar() {


acoustic.play();
}

public void offGuitar() {


acoustic.leaveGuitar();
}
}
}

2.6.4. Ejemplo con acceso a BD

El proyecto es una aplicacin que maneja contactos personales


(nombre, telfonos, correos, etc.), y fue desarrollada por un grupo
reducido

de

desarrolladores.

Para

empezar

tenemos

una

interfaz Contacto que implementarn todos los tipos diferentes de


contactos que existan y que consta de lo siguiente:

Las clases que implementan sta interfaz son Amigo y Familiar, les
recuerdo que las clases sern de lo mas simple, con el fin de enfocarnos
nicamente en la implementacin del patrn:

El problema surgi cuando se le encarg a un nuevo integrante del


equipo

desarrollar

una

nueva

clase

para

los

contactos

que

fuera CompaerosTrabajo, dicha clase qued de la siguiente manera:

Como se puede observar la clase es totalmente diferente al estndar de


las dems clases desarrolladas. Para solucionar esto se cre una clase
que adaptara la clase CompaerosTrabajopara que implemente la
interfaz Contacto.

Listo! Ya tenemos nuestra clase CompaerosTrabajo adaptada y que


implementa la interfaz Contacto. Si la llamamos desde nuestro cdigo
principal tendremos lo siguiente.

2.7.

Patrn Bridge

2.7.1. Definicin

El patrn Bridge, tambin conocido como Handle/Body, es una


tcnica usada en programacin para desacoplar una abstraccin
de su implementacin, de manera que ambas puedan ser
modificadas independientemente sin necesidad de alterar por ello
la otra.

Esto es, se desacopla una abstraccin de su implementacin para


que puedan variar independientemente.

2.7.2. Esquema

Abstraction define una interface abstracta. Mantiene una


referencia a un objeto de tipo Implementor.

RefinedAbstraction extiende la interface definida por Abstraction

Implementor define la interface para la implementacin de clases.


Esta interface no se tiene que corresponder exactamente con la
interface de Abstraction; de hecho, las dos interfaces pueden ser
bastante diferente. Tpicamente la interface Implementorprovee

slo operaciones primitivas, y Abstraction define operaciones de


alto nivel basadas en estas primitivas.

ConcreteImplementor implementa la interface de Implementor y


define su implementacin concreta.

2.7.3. Ejemplo General

interface Implementador {
public abstract void operacion();
}

/** primera implementacion de Implementador **/


class ImplementacionA implements Implementador{
public void operacion() {
System.out.println("Esta es la implementacion A");
}
}
/** segunda implementacion de Implementador **/
class ImplementacionB implements Implementador{
public void operacion() {
System.out.println("Esta es una implementacion de B");
}
}
/** interfaz de abstraccin **/
interface Abstraccion {
public void operacion();
}
/** clase refinada que implementa la abstraccion **/
class AbstraccionRefinada implements Abstraccion{
private Implementador implementador;

public AbstraccionRefinada(Implementador implementador){


this.implementador = implementador;
}
public void operacion(){
implementador.operacion();
}
}
/** aplicacion que usa el patrn Bridge **/
public class EjemploBridge {
public static void main(String[] args) {
Abstraccion[] abstracciones = new Abstraccion[2];
abstracciones[0] = new AbstraccionRefinada(new ImplementacionA());
abstracciones[1] = new AbstraccionRefinada(new ImplementacionB());
for(Abstraccion abstraccion:abstracciones)
abstraccion.operacion();
}
}
2.7.4. Ejemplo con acceso a BD

public class Abstraction


{
public ImplementationBase Implementer { get; set; }

public virtual void Operation()


{
Console.WriteLine("ImplementationBase:Operation()");
Implementer.OperationImplementation();
}
}

public class RefinedAbstraction : Abstraction


{
public override void Operation()
{
Console.WriteLine("RefinedAbstraction:Operation()");
Implementer.OperationImplementation();
}
}

public abstract class ImplementationBase


{
public abstract void OperationImplementation();
}

public class ConcreteImplementation1 : ImplementationBase


{
public override void OperationImplementation()
{
Console.WriteLine("ConcreteImplementation1:OperationImplementation()");
}
}
public class ConcreteImplementation2 : ImplementationBase
{
public override void OperationImplementation()
{
Console.WriteLine("ConcreteImplementation2:OperationImplementation()");

}
}

2.8.

Patrn Composite

2.8.1. Definicin

El patrn Composite sirve para construir objetos complejos a


partir de otros ms simples y similares entre s, gracias a la
composicin recursiva y a una estructura en forma de rbol.

Esto simplifica el tratamiento de los objetos creados, ya que al


poseer todos ellos una interfaz comn, se tratan todos de la
misma manera. Dependiendo de la implementacin, pueden
aplicarse procedimientos al total o una de las partes de la
estructura compuesta como si de un nodo final se tratara, aunque
dicha parte est compuesta a su vez de muchas otras. Un claro
ejemplo de uso extendido de este patrn se da en los entornos de
programacin 2D para aplicaciones grficas. Un videojuego
puede contener diferentes capas "layers" de sprites (como una
capa de enemigos) pudindose invocar un mtodo que acte
sobre toda esta capa de sprites a la vez (por ejemplo, para
ocultarlos, darles un filtro de color etc.).

2.8.2. Esquema

Component
Es la abstraccin de todos los componentes, incluyendo los compuestos
declara la interfaz de objetos en la composicin (Opcional) define una
interfaz para acceder a los padres de un componente en la estructura
recursiva, y aplica esto si lo considera apropiado

Leaf
Representa objetos hoja en la composicin implementa todos los
mtodos de componentes

Composite

Representa un compuesto de componentes (componente de tener hijos)


implementa mtodos para manipular los nios implementa todos los
mtodos de componentes, en general, por delegacin a sus hijos

2.8.3. Ejemplo General


import java.util.*;
public abstract class Componente
{
protected String nombre;
public Componente (String nombre)
{
this.nombre = nombre;
}
abstract public void agregar(Componente c);
abstract public void eliminar(Componente c);
abstract public void mostrar(int profundidad);
}
class Compuesto extends Componente

{
private ArrayList<Componente> hijo = new ArrayList<Componente>();
public Compuesto (String name)
{
super(name);
}
@Override
public void agregar(Componente componente)
{
hijo.add(componente);
}
@Override
public void eliminar(Componente componente)
{
hijo.remove(componente);
}
@Override
public void mostrar(int profundidad)
{
System.out.println(nombre + " nivel: " + profundidad);
for (int i = 0; i < hijo.size(); i++)
hijo.get(i).mostrar(profundidad + 1);
}
}
class Hoja extends Componente
{
public Hoja (String nombre)
{
super(nombre);

}
public void agregar(Componente c)
{
System.out.println("no se puede agregar la hoja");
}
public void eliminar(Componente c)
{
System.out.println("no se puede quitar la hoja");
}
public void mostrar(int depth)
{
System.out.println('-' + "" + nombre);
}
}
public class Client
{
public static void main(String[] args)
{
Compuesto raiz = new Compuesto("root");
raiz.agregar(new Hoja("hoja A"));
raiz.agregar(new Hoja("hoja B"));
Compuesto comp = new Compuesto("compuesto X");
comp.agregar(new Hoja("hoja XA"));
comp.agregar(new Hoja("hoja XB"));
raiz.agregar(comp);
raiz.agregar(new Hoja("hoja C"));
Hoja l = new Hoja("hoja D");
raiz.agregar(l);
raiz.eliminar(l);

raiz.mostrar(1);
}
}

2.8.4. Ejemplo con acceso a BD

package corepatterns.apps.psa.ejb;

import corepatterns.apps.psa.core.*;
import corepatterns.apps.psa.dao.*;
import java.sql.*;
import javax.sql.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;

public class ResourceEntity implements EntityBean {


public String employeeId;
public String lastName;
public String firstName;
public String departmentId;
public String practiceGroup;
public String title;
public String grade;
public String email;
public String phone;
public String cell;
public String pager;
public String managerId;

// Collection of BlockOutTime Dependent objects


public Collection blockoutTimes;

// Collection of SkillSet Dependent objects


public Collection skillSets;

...

private EntityContext context;


// Entity Bean methods implementation
public String ejbCreate(ResourceTO resource) throws
CreateException {
try {
this.employeeId = resource.employeeId;
setResourceData(resource);
getResourceDAO().create(resource);
} catch(Exception ex) {
throw new EJBException("Reason:" + ...);
}
return this.employeeId;
}

public String ejbFindByPrimaryKey(String primaryKey)


throws FinderException {
boolean result;
try {
ResourceDAO resourceDAO = getResourceDAO();
result =
resourceDAO.selectByPrimaryKey(primaryKey);

} catch(Exception ex) {
throw new EJBException("Reason:" + ...);
}
if(result) {
return primaryKey;
}
else {
throw new ObjectNotFoundException(...);
}
}

public void ejbRemove() {


try {
// Remove dependent objects
if(this.skillSets != null) {

SkillSetDAO skillSetDAO = getSkillSetDAO();


skillSetDAO.setResourceID(employeeId);
skillSetDAO.deleteAll();
skillSets = null;
}
if(this.blockoutTime != null) {
BlockOutTimeDAO blockouttimeDAO =
getBlockOutTimeDAO();
blockouttimeDAO.setResourceID(employeeId);
blockouttimeDAO.deleteAll();
blockOutTimes = null;
}

// Remove the resource from the persistent store


ResourceDAO resourceDAO = new
ResourceDAO(employeeId);
resourceDAO.delete();
} catch(ResourceException ex) {
throw new EJBException("Reason:"+...);
} catch(BlockOutTimeException ex) {
throw new EJBException("Reason:"+...);
} catch(Exception exception) {
...
}
}
public void setEntityContext(EntityContext context)
{
this.context = context;
}

public void unsetEntityContext() {


context = null;
}

public void ejbActivate() {


employeeId = (String)context.getPrimaryKey();
}

public void ejbPassivate() {


employeeId = null;
}

public void ejbLoad() {


try {
// load the resource info from
ResourceDAO resourceDAO = getResourceDAO();
setResourceData((ResourceTO)
resourceDAO.load(employeeId));

// Load other dependent objects, if necessary


...
} catch(Exception ex) {
throw new EJBException("Reason:" + ...);
}
}

public void ejbStore() {


try {
// Store resource information
getResourceDAO().update(getResourceData());

// Store dependent objects as needed


...
} catch(SkillSetException ex) {
throw new EJBException("Reason:" + ...);
} catch(BlockOutTimeException ex) {
throw new EJBException("Reason:" + ...);
}
...
}
public void ejbPostCreate(ResourceTO resource) {

// Method to Get Resource Transfer Object


public ResourceTO getResourceTO() {
// create a new Resource Transfer Object
ResourceTO resourceTO = new
ResourceTO(employeeId);

// copy all values


resourceTO.lastName = lastName;
resourceTO.firstName = firstName;
resourceTO.departmentId = departmentId;
...
return resourceTO;
}

public void setResourceData(ResourceTO resourceTO) {


// copy values from Transfer Object into entity bean
employeeId = resourceTO.employeeId;
lastName = resourceTO.lastName;
...
}

// Method to get dependent Transfer Objects


public Collection getSkillSetsData() {
// If skillSets is not loaded, load it first.
// See Lazy Load strategy implementation.

return skillSets;

}
...

// other get and set methods as needed


...

// Entity bean business methods


public void addBlockOutTimes(Collection moreBOTs)
throws BlockOutTimeException {
// Note: moreBOTs is a collection of
// BlockOutTimeTO objects
try {
Iterator moreIter = moreBOTs.iterator();
while(moreIter.hasNext()) {
BlockOutTimeTO botTO = (BlockOutTimeTO)
moreIter.next();
if (! (blockOutTimeExists(botTO))) {
// add BlockOutTimeTO to collection
botTO.setNew();
blockOutTime.add(botTO);
} else {
// BlockOutTimeTO already exists, cannot add
throw new BlockOutTimeException(...);
}
}
} catch(Exception exception) {
throw new EJBException(...);
}
}

public void addSkillSet(Collection moreSkills)


throws SkillSetException {
// similar to addBlockOutTime() implementation
...
}

...

public void updateBlockOutTime(Collection updBOTs)


throws BlockOutTimeException {
try {
Iterator botIter = blockOutTimes.iterator();
Iterator updIter = updBOTs.iterator();
while (updIter.hasNext()) {
BlockOutTimeTO botTO = (BlockOutTimeTO)
updIter.next();
while (botIter.hasNext()) {
BlockOutTimeTO existingBOT =
(BlockOutTimeTO) botIter.next();
// compare key values to locate BlockOutTime
if (existingBOT.equals(botTO)) {
// Found BlockOutTime in collection
// replace old BlockOutTimeTO with new one
botTO.setDirty(); //modified old dependent
botTO.resetNew(); //not a new dependent
existingBOT = botTO;
}
}

}
} catch (Exception exc) {
throw new EJBException(...);
}
}

public void updateSkillSet(Collection updSkills)


throws CommitmentException {
// similar to updateBlockOutTime...
...
}

...

}
2.9.

Patrn Decorator

2.9.1. Definicin

El patrn Decorator responde a la necesidad de aadir


dinmicamente funcionalidad a un Objeto. Esto nos permite no
tener que crear sucesivas clases que hereden de la primera
incorporando la nueva funcionalidad, sino otras que la
implementan y se asocian a la primera.

2.9.2. Esquema

Componente
Dene la interfaz para los objetos que pueden tener
responsabilidades aadidas.

Componente Concreto
Dene un objeto al cual se le puede agregar responsabilidades
adicionales.

Decorador

Mantiene una referencia al componente asociado. Implementa


la interfaz de la superclase Componente delegando en el
componente asociado.

Decorador Concreto

Aade responsabilidades al componente.

2.9.3. Ejemplo General


public abstract class Componente{
abstract public void operacion();
}
public class ComponenteConcreto extends Componente{
public void operacion(){
System.out.println("ComponenteConcreto.operacion()");
}
}
public abstract class Decorador extends Componente{
private Componente _componente;
public Decorador(Componente componente){
_componente = componente;
}
public void operacion(){
_componente.operacion();
}
}

public class DecoradorConcretoA extends Decorador{


private String _propiedadAadida;

public DecoradorConcretoA(Componente componente){


super(componente);

public void operacion(){


super.operacion();
_propiedadAadida = "Nueva propiedad";
System.out.println("DecoradorConcretoA.operacion()");
}
}
public class DecoradorConcretoB extends Decorador{
public DecoradorConcretoB(Componente componente){
super(componente);
}
public void operacion(){
super.operacion();
comportamientoAadido();
System.out.println("DecoradorConcretoB.operacion()");
}
public void comportamientoAadido(){
System.out.println("Comportamiento B aadido");
}
}
public class Cliente{
public static void main(String[] args){
ComponenteConcreto c = new ComponenteConcreto();
DecoradorConcretoA d1 = new DecoradorConcretoA(c);
DecoradorConcretoB d2 = new DecoradorConcretoB(d1);
d2.operacion();
}
}

2.9.4. Ejemplo con acceso a BD

2.10. Patrn Facade

2.10.1.

Definicin

Los patrones de diseo dan una solucin probada y


documentada a problemas de desarrollo de software que
aparecen en un contexto similar. El patrn de
diseo Fachada (Facade) es un tipo de patrn estructural.

2.10.2.

Esquema

Fachada (Facade)

Conoce qu clases del subsistema son responsables de una


determinada peticin, y delega esas peticiones de los clientes a
los objetos apropiados del subsistema.

Subclases (ModuleA, ModuleB, ModuleC...):

Implementan la funcionalidad del subsistema. Realizan el


trabajo solicitado por la fachada. No conocen la existencia de la
fachada.

2.10.3.

Ejemplo General

package com.genbetadev;
public class Impresora {
private String tipoDocumento;
private String hoja;
private boolean color;
private String texto;
public String getTipoDocumento() {
return tipoDocumento;
}
public void setTipoDocumento(String tipoDocumento) {

this.tipoDocumento = tipoDocumento;
}
public String getHoja() {
return hoja;
}
public void setHoja(String hoja) {
this.hoja = hoja;
}
}
Se trata de una clase sencilla que imprime documentos en uno u otro formato.
El cdigo de la clase cliente nos ayudar a entender mejor su funcionamiento.

package com.genbetadev;
public class PrincipalCliente {
public static void main(String[] args) {
Impresora i = new Impresora();
i.setHoja("a4");
i.setColor(true);
i.setTipoDocumento("pdf");
i.setTexto("texto 1");
i.imprimirDocumento();
Impresora i2 = new Impresora();
i2.setHoja("a4");
i2.setColor(true);
i2.setTipoDocumento("pdf");
i2.setTexto("texto 2");
i2.imprimirDocumento();
Impresora i3 = new Impresora();
i3.setHoja("a3");
i3.setColor(false);

i3.setTipoDocumento("excel");
i3.setTexto("texto 3");
i3.imprimirDocumento();}}
Como podemos ver la clase cliente se encarga de invocar a la impresora, y
configurarla para despus imprimir varios documentos .Ahora bien
prcticamente todos los documentos que escribimos tienen la misma estructura
(formato A4, Color , PDF). Estamos continuamente repitiendo cdigo. Vamos a
construir una nueva clase FachadaImpresoraNormal que simplifique la
impresin de documentos que sean los ms habituales.

package com.genbetadev;
public class FachadaImpresoraNormal {
Impresora impresora;
public FachadaImpresoraNormal(String texto) {
super();
impresora= new Impresora();
impresora.setColor(true);
impresora.setHoja("A4");
impresora.setTipoDocumento("PDF");
impresora.setTexto(texto);
}
public void imprimir() {
impresora.imprimirDocumento();} }
De esta forma el cliente quedar mucho ms sencillo :
package com.genbetadev;
public class PrincipalCliente2 {
public static void main(String[] args) {
FachadaImpresoraNormal fachada1= new
FachadaImpresoraNormal("texto1");
fachada1.imprimir();
FachadaImpresoraNormal fachada2= new
FachadaImpresoraNormal("texto2");

fachada2.imprimir();
Impresora i3 = new Impresora();
i3.setHoja("a4");
i3.setColor(true);
i3.setTipoDocumento("excel");
i3.setTexto("texto 3");
i3.imprimirDocumento();} }

2.10.4. Ejemplo con acceso a BD


package com.genbetadev;
public class Impresora {
private String tipoDocumento;
private String hoja;
private boolean color;
private String texto;
public String getTipoDocumento() {
return tipoDocumento; }
public void setTipoDocumento(String tipoDocumento) {
this.tipoDocumento = tipoDocumento;}
public String getHoja() {
return hoja; }
public void setHoja(String hoja) {
this.hoja = hoja;} }
Se trata de una clase sencilla que imprime documentos en uno u otro formato.
El cdigo de la clase cliente nos ayudar a entender mejor su funcionamiento.

package com.genbetadev;
public class PrincipalCliente {
public static void main(String[] args) {
Impresora i = new Impresora();

i.setHoja("a4");
i.setColor(true);
i.setTipoDocumento("pdf");
i.setTexto("texto 1");
i.imprimirDocumento();
Impresora i2 = new Impresora();
i2.setHoja("a4");
i2.setColor(true);
i2.setTipoDocumento("pdf");
i2.setTexto("texto 2");
i2.imprimirDocumento();
Impresora i3 = new Impresora();
i3.setHoja("a3");
i3.setColor(false);
i3.setTipoDocumento("excel");
i3.setTexto("texto 3");
i3.imprimirDocumento();} }
Como podemos ver la clase cliente se encarga de invocar a la impresora, y
configurarla para despus imprimir varios documentos .Ahora bien
prcticamente todos los documentos que escribimos tienen la misma estructura
(formato A4, Color , PDF). Estamos continuamente repitiendo cdigo. Vamos a
construir una nueva clase FachadaImpresoraNormal que simplifique la
impresin de documentos que sean los ms habituales.
package com.genbetadev;
public class FachadaImpresoraNormal {
Impresora impresora;
public FachadaImpresoraNormal(String texto) {
super();
impresora= new Impresora();
impresora.setColor(true);
impresora.setHoja("A4");

impresora.setTipoDocumento("PDF");
impresora.setTexto(texto); }
public void imprimir() {
impresora.imprimirDocumento();}}
De esta forma el cliente quedar mucho ms sencillo :
package com.genbetadev;
public class PrincipalCliente2 {
public static void main(String[] args) {
FachadaImpresoraNormal fachada1= new
FachadaImpresoraNormal("texto1");
fachada1.imprimir();
FachadaImpresoraNormal fachada2= new
FachadaImpresoraNormal("texto2");
fachada2.imprimir();
Impresora i3 = new Impresora();
i3.setHoja("a4");
i3.setColor(true);
i3.setTipoDocumento("excel");
i3.setTexto("texto 3");
i3.imprimirDocumento();
}package com.ezjamvc.modelo.facade;
import com.ezjamvc.modelo.dao.ArticuloDAO;
import com.ezjamvc.modelo.dto.ArticuloDTO;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/** @author asuncion */
public class ArticuloFacade {
private Connection cnn;
private ArticuloDAO dao;

public ArticuloFacade(Connection cnn) {


this.cnn = cnn;
dao = new ArticuloDAO();
}
public void crear(ArticuloDTO dto) throws SQLException {
dao.create(dto, cnn);
}
public List listar() throws SQLException {
return dao.loadAll(cnn);
}
public ArticuloDTO leer(ArticuloDTO dto)throws SQLException {
return dao.load(dto, cnn);
}
public void actualiza(ArticuloDTO dto)throws SQLException {
dao.update(dto, cnn);
}
public void elimina(ArticuloDTO dto)throws SQLException {
dao.delete(dto, cnn);
}
}

package com.ezjamvc.modelo.delegate;
import com.ezjamvc.modelo.dto.ArticuloDTO;
import com.ezjamvc.modelo.facade.ArticuloFacade;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

/**
*
* @author asuncion
*/
public class EzjaMVCDelegate {
private Connection cnn;
private ArticuloFacade artFacade;
public EzjaMVCDelegate() {
String user = "root";
String pwd = "admin";
String url = "jdbc:mysql://localhost:3306/EzjaMVC";
String mySqlDriver = "com.mysql.jdbc.Driver";
try {
Class.forName(mySqlDriver);
cnn = DriverManager.getConnection(url, user, pwd);
} catch (Exception e) {
e.printStackTrace();
}
artFacade = new ArticuloFacade(cnn);
}
//Codigo para los Articulos
public void crearArticulo(ArticuloDTO dto) throws SQLException {
artFacade.crear(dto);
}
public List listarArticulos() throws SQLException {
return artFacade.listar();
}
public ArticuloDTO leerArticulo(ArticuloDTO dto) throws SQLException {
return artFacade.leer(dto);

}
public void actualiza(ArticuloDTO dto) throws SQLException {
artFacade.actualiza(dto);
}
public void elimina(ArticuloDTO dto) throws SQLException {
artFacade.elimina(dto);
}
}
Al revisar el codigo, nos podemos dar cuenta que al momento de definir el
constructor, se obtiene una conexion a la base de datos, la cual se pasa como
parametro a la instancia de ArticuloFacade que se crea.
Cabe mencionar que la estructura final de la aplicacion es la siguiente.

Ahora modificaremos ligeramente la clase de prueba para verificar el


funcionamiento de la aplicacion.
package com.ezjamvc.vista.formularios;
import com.ezjamvc.modelo.delegate.EzjaMVCDelegate;
import com.ezjamvc.modelo.dto.ArticuloDTO;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
/** @author asuncion */
public class PruebaDelegate {
public PruebaDelegate() {
}
public static void main(String[] args) {
EzjaMVCDelegate del = new EzjaMVCDelegate();
ArticuloDTO dto = new ArticuloDTO();
try {
System.out.println(del.listarArticulos());
} catch (SQLException ex) {

Logger.getLogger(PruebaDelegate.class.getName()).log(Level.SEVERE, null,
ex); } }}
Y con esto terminamos con todas las capas del modelo de la aplicacion
propuesta. En la cual se aplican los 4 patrones antes mencionados:
1.
2.
3.
4.

Data Transfers object


Data Access object
Session Facade
Bussines Delegate

2.11. Patrn Chain of Responsability

2.11.1.

Definicin

El patrn de diseo Chain of Responsibility es un patrn de


comportamiento que evita acoplar el emisor de una peticin a su
receptor dando a ms de un objeto la posibilidad de responder a
una peticin. Para ello, se encadenan los receptores y pasa la
peticin a travs de la cadena hasta que es procesada por algn
objeto. Este patrn es utilizado a menudo en el contexto de las
interfaces grficas de usuario donde un objeto puede estar
compuesto de varios objetos (que generalmente heradn de una
super clase "vista"). No se debe confundir con el
patrn Composite (patrn de diseo) que se basa en un concepto
similar.

2.11.2.

Esquema

Manejador
Define una interfaz para tratar las peticiones. Opcionalmente,
implementa el enlace al sucesor.

ManejadorConcreto

Trata las peticiones de las que es responsable; si el


ManejadorConcreto puede manejar la peticin, lo hace; en caso
contrario la reenva a su sucesor.

Cliente
Inicializa la peticin a un Manejador Concreto de la cadena.

2.11.3.

Ejemplo General

public class Cliente {


public static void main(String argv[]) {
Unidad smith = new Coronel("Smith", null);
Unidad truman = new Coronel("Truman", "Tomar posicin enemiga");
Unidad ryan = new Soldado("Ryan");
Unidad rambo = new Soldado("Rambo");

System.out.println(rambo.orden());

// rambo ->

rambo.establecerMando(truman);
System.out.println(rambo.orden());

// rambo -> truman

ryan.establecerMando(rambo);
System.out.println(ryan.orden());
}}
public abstract class Unidad {
public Unidad(String nombre) {

// ryan -> rambo -> truman

_mando = null;
_nombre = nombre; }
public String toString() { return _nombre; }
public void establecerMando(Unidad mando) { _mando = mando; }
public String orden() {
return (_mando != null ? _mando.orden() : "(sin orden)");
}
private Unidad _mando;
private String _nombre;
}
public class Coronel extends Unidad {
public Coronel(String nombre, String orden) {
super(nombre);
_orden = orden;
}
public String orden()

{ return (_orden != null ? _orden : super.orden()); }

public String toString() { return ("Coronel " + super.toString()); }


private String _orden;
}
public class Soldado extends Unidad {
public Soldado(String nombre) {
super(nombre);
}
public String toString() { return ("Soldado " + super.toString()); }
}

2.11.4.

Ejemplo con acceso a BD

2.12. Patrn Command

2.12.1.

Definicin

Este patrn permite solicitar una operacin a un objeto sin


conocer realmente el contenido de esta operacin, ni el receptor
real de la misma. Para ello se encapsula la peticin como un
objeto, con lo que adems facilita la parametrizacin de los
mtodos.

2.12.2.

Esquema

AbstractCommand.
Clase que ofrece una interfaz para la ejecucin de rdenes.
Define los mtodos do y undo que se implementarn en cada
clase concreta.

ConcreteCommand.
Clase que implementa una orden concreta y sus mtodos do y
undo. Su constructor debe inicializar los parmetros de la orden.

Invoker.
Clase que instancia las rdenes, puede a su vez ejecutarlas
inmediatamente (llamando a do) o dejar que el
CommandManager lo haga.

CommandManager.
Responsable de gestionar una coleccin de objetos orden
creadas por el Invoker. llamar a los mtodos do y unDo.
Gestionar su secuenciacin y reordenacin (sobre la base de
prioridades por ejemplo).

2.12.3. Ejemplo General


/* The Invoker class */
public class Switch {
private Command flipUpCommand;
private Command flipDownCommand;
public Switch(Command flipUpCmd, Command flipDownCmd) {
this.flipUpCommand = flipUpCmd;
this.flipDownCommand = flipDownCmd; }
public void flipUp() {
flipUpCommand.execute();}
public void flipDown() {
flipDownCommand.execute(); }}
public class Light {
public Light() { }
public void turnOn() {
System.out.println("The light is on");

public void turnOff() {


System.out.println("The light is off"); }}
public interface Command {
void execute();
}
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight=light; }
public void execute(){
theLight.turnOn();}}

public class FlipDownCommand implements Command {


private Light theLight;
public FlipDownCommand(Light light) {
this.theLight=light; }
public void execute() {
theLight.turnOff(); }}

public class PressSwitch {


public static void main(String[] args){
if (args.length != 1) {
System.err.println("Argument \"ON\" or \"OFF\" is required.");
System.exit(-1); }
Light lamp = new Light();
Command switchUp = new FlipUpCommand(lamp);
Command switchDown = new FlipDownCommand(lamp);
Switch mySwitch = new Switch(switchUp, switchDown);

switch (args[0]) {
case "ON":
mySwitch.flipUp();
break;
case "OFF":
mySwitch.flipDown();
break;
default:
System.err.println("Argument \"ON\" or \"OFF\" is required.");
System.exit(-1);
}
}
}

2.12.4.

Ejemplo con acceso a BD

using Oracle.DataAccess.Client;
public class OracleDatabase : Database
{
public override IDbConnection CreateConnection()
{
return new OracleConnection(connectionString);
}
public override IDbCommand CreateCommand()
{
return new OracleCommand();
}
public override IDbConnection CreateOpenConnection()
{

OracleConnection connection = (OracleConnection)CreateConnection();


connection.Open();
return connection;
}
public override IDbCommand CreateCommand(string commandText,
IDbConnection connection)
{
OracleCommand command = (OracleCommand)CreateCommand();
command.CommandText = commandText;
command.Connection = (OracleConnection)connection;
command.CommandType = CommandType.Text;
return command;
}
public override IDbCommand CreateStoredProcCommand(string procName,
IDbConnection connection)
{
OracleCommand command = (OracleCommand)CreateCommand();
command.CommandText = procName;
command.Connection = (OracleConnection)connection;
command.CommandType = CommandType.StoredProcedure;
return command;
}
public override IDataParameter CreateParameter(string parameterName,
object parameterValue)
{
return new OracleParameter(parameterName, parameterValue);
}
}

2.13. Patrn Observer

2.13.1.

Definicin

Este patrn tambin se conoce como el patrn de publicacininscripcin o modelo-patrn. Estos nombres sugieren las ideas
bsicas del patrn, que son: el objeto de datos, que se le puede
llamar Sujeto a partir de ahora, contiene atributos mediante los
cuales cualquier objeto Observador o vista se puede suscribir a l
pasndole una referencia a s mismo. El Sujeto mantiene as una
lista de las referencias a sus observadores. Los observadores a
su vez estn obligados a implementar unos mtodos
determinados mediante los cuales el Sujeto es capaz de notificar
a sus observadores suscritos los cambios que sufre para que
todos ellos tengan la oportunidad de refrescar el contenido
representado. De manera que cuando se produce un cambio en
el Sujeto, ejecutado, por ejemplo, por alguno de los observadores,
el objeto de datos puede recorrer la lista de observadores
avisando a cada uno. Este patrn suele observarse en
los frameworks de interfaces grficas orientados a objetos, en los
que la forma de capturar los eventos es suscribir listeners a los
objetos que pueden disparar eventos.

2.13.2.

Esquema
Sujeto (Subject):
El sujeto proporciona una interfaz para agregar
(attach) y eliminar (detach) observadores. El Sujeto
conoce a todos sus observadores.

Observador (Observer):

Define el mtodo que usa el sujeto para notificar


cambios en su estado (update/notify).

Sujeto Concreto (ConcreteSubject):


Mantiene el estado de inters para los observadores
concretos y los notifica cuando cambia su estado. No
tienen por qu ser elementos de la misma jerarqua.

Observador Concreto (ConcreteObserver):


Mantiene una referencia al sujeto concreto e
implementa la interfaz de actualizacin, es decir,
guardan la referencia del objeto que observan, as en
caso de ser notificados de algn cambio, pueden
preguntar sobre este cambio.

2.13.3.
import java.util.*;

Ejemplo General

class FuenteEvento extends Observable implements Runnable {


public void run() {
while (true) {
String respuesta = new Scanner(System.in).next();
setChanged();
notifyObservers(respuesta);
}
}
}
import java.util.Observable;
import static java.lang.System.out;

class MiApp {
public static void main(String[] args) {
out.println("Introducir Texto >");
FuenteEvento fuenteEvento = new FuenteEvento();

fuenteEvento.addObserver( (Observable obj, Object arg) -> {


out.println("\nRespuesta recibida: " + arg);
});

new Thread(fuenteEvento).start();
}
}

2.13.4.
import java.util.*;

Ejemplo con acceso a BD

public class Database implements Subject


{
private Vector<Observer> observers;

public Database()
{
observers = new Vector<Observer>();
}
.
}
Cuando se utiliza un vector, hacer el seguimiento de los observadores es
simple. Cuando un observador quiere dar de alta, se llama al mtodo
registerObserver del sujeto, hacindose pasar como un objeto. El sujeto objeto de nuestra clase de base de datos - slo tiene que aadir que el vector
de observador a los observadores en el mtodo registerObserver, utilizando el
mtodo de complemento de la clase Vector.
import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;
public Database()
{
observers = new Vector<Observer>();
}
public void registerObserver(Observer o)
{
observers.add(o);
}
.

.
.
}

Qu hay de la eliminacin de un observador del vector de los observadores?


No hay problema. Cuando se quiere eliminar un objeto de un vector, puede
utilizar el mtodo de eliminacin de los vectores; aqu est la manera que
funciona en el mtodo removeObserver de la clase de base de datos:
import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;

public Database()
{
observers = new Vector<Observer>();
}

public void registerObserver(Observer o)


{
observers.add(o);
}

public void removeObserver(Observer o)


{
observers.remove(o);
}
.
.
.

Cuando el usuario realmente hace algo con la base de datos - elimina un


registro, por ejemplo - que l llama mtodo editRecord de la clase de base de
datos. Por ejemplo, para eliminar el registro 1, es posible llamar a este mtodo
como este:
database.editRecord(delete, record 1);

Esto es lo que el mtodo editRecord se ve as: Cuando se llama a este mtodo,


se le pasa la operacin de base de datos que desea realizar y el registro que
desea trabajar, tanto como cadenas en este ejemplo. Esas cadenas se
almacenan para que puedan ser transmitidas a los observadores. Una vez
guardados los hilos, el mtodo notifyObservers, que viene a continuacin, se
llama a notificar a todos los observadores.
import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;
private String operation;
private String record;

public Database()
{
observers = new Vector<Observer>();
}
.
.
.
public void editRecord(String operation, String record)
{
this.operation = operation;
this.record = record;

notifyObservers();
}
}

Aqu est la carne del cdigo, la parte que notifica a cada observador que ha
habido un cambio: el mtodo notifyObservers. Cada observador implementa la
interfaz de este ejemplo Observador - que significa que tiene un mtodo de
actualizacin - por lo notifyObservers acaba de bucle para todos los
observadores registrados en el vector de observadores, llamando al mtodo de
actualizacin de cada uno con la operacin de base de datos y registro
afectado.
import java.util.*;
public class Database implements Subject
{
private Vector<Observer> observers;
private String operation;
private String record;
.
.
.
public void notifyObservers()
{
for (int loopIndex = 0; loopIndex < observers.size(); loopIndex++) {
Observer observer = (Observer)observers.get(loopIndex);
observer.update(operation, record);
}
}

public void editRecord(String operation, String record)


{
this.operation = operation;

this.record = record;
notifyObservers();
}
}

Eso es todo lo que necesita para Database.java, el tema en este ejemplo. El


tema le permitir observadores registran a s mismos, anular el registro de s
mismos, y recibir una notificacin cuando un registro de base de datos ha sido
editado (que lo hace con el mtodo editRecord de la clase de base de datos).
Todo lo que queda por hacer para conseguir este espectculo en el camino es
la creacin de los propios observadores.
2.14. Patrn Mediator

2.14.1.

2.14.2.

Definicin

El patrn mediador define un objeto que encapsula cmo un


conjunto de objetos interactan. Este patrn de diseo est
considerado como un patrn de comportamiento debido al
hecho de que puede alterar el comportamiento del programa
en ejecucin.

Esquema

Mediador - define la interfaz para la comunicacin entre


objetos amigos

MediadorConcreto - implementa la interfaz Mediador y coordina


la comunicacin entre objetos amigos. Es consciente de todos
los amigos y su propsito en lo que concierne a la comunicacin
entre ellos.

AmigoConcreto - se comunica con otros amigos a travs de


su Mediador

2.14.3. Ejemplo General


import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//Interfaz Amigo
interface Command {
void execute();
}

//Mediador Abstracto
interface IMediator {
void book();
void view();
void search();
void registerView(BtnView v);
void registerSearch(BtnSearch s);
void registerBook(BtnBook b);
void registerDisplay(LblDisplay d);
}

//Mediador Concreto
class Mediator implements IMediator {

BtnView btnView;
BtnSearch btnSearch;
BtnBook btnBook;
LblDisplay show;

//....
void registerView(BtnView v) {
btnView = v;
}

void registerSearch(BtnSearch s) {
btnSearch = s;
}

void registerBook(BtnBook b) {
btnBook = b;
}

void registerDisplay(LblDisplay d) {
show = d;
}

void book() {
btnBook.setEnabled(false);
btnView.setEnabled(true);
btnSearch.setEnabled(true);
show.setText("booking...");
}

void view() {
btnView.setEnabled(false);
btnSearch.setEnabled(true);
btnBook.setEnabled(true);
show.setText("viewing...");
}

void search() {
btnSearch.setEnabled(false);
btnView.setEnabled(true);
btnBook.setEnabled(true);
show.setText("searching...");
}

//Un amigo concreto


class BtnView extends JButton implements Command {

IMediator med;

BtnView(ActionListener al, IMediator m) {


super("View");
addActionListener(al);
med = m;
med.registerView(this);
}

public void execute() {


med.view();
}

//Un amigo concreto


class BtnSearch extends JButton implements Command {

IMediator med;

BtnSearch(ActionListener al, IMediator m) {


super("Search");
addActionListener(al);
med = m;
med.registerSearch(this);
}

public void execute() {


med.search();
}

//Un amigo concreto


class BtnBook extends JButton implements Command {

IMediator med;

BtnBook(ActionListener al, IMediator m) {


super("Book");
addActionListener(al);
med = m;
med.registerBook(this);
}

public void execute() {


med.book();
}

class LblDisplay extends JLabel {

IMediator med;

LblDisplay(IMediator m) {
super("Just start...");
med = m;
med.registerDisplay(this);
setFont(new Font("Arial", Font.BOLD, 24));
}

class MediatorDemo extends JFrame implements ActionListener {

IMediator med = new Mediator();

MediatorDemo() {
JPanel p = new JPanel();
p.add(new BtnView(this, med));
p.add(new BtnBook(this, med));
p.add(new BtnSearch(this, med));
getContentPane().add(new LblDisplay(med), "North");
getContentPane().add(p, "South");
setSize(400, 200);
setVisible(true);
}

public void actionPerformed(ActionEvent ae) {


Command comd = (Command) ae.getSource();
comd.execute();
}

public static void main(String[] args) {


new MediatorDemo();
}

2.14.4.

Ejemplo con acceso a BD

Utilizando el patrn de diseo de la fachada que le "ocultar" todas las


relaciones de la funcionalidad existente detrs de un solo "interfaz" el que
expone la fachada.
Client code:

Logger logger = new Logger();


logger.initLogger("someLogger");
logger.debug("message");
La aplicacin puede implicar la interaccin de muchos objetos. Pero al final, la
funcionalidad ya existe. Probablemente, el mtodo "debug" se implementa
como sigue:
Implementation:

class Logger {

private LoggerImpl internalLogger;


private LoggerManager manager;

public void initLogger( String loggerName ) {


this.internalLogger = manager.getLogger( loggerName );
}

public void debug( String message ) {


this.internalLogger.debug( message );
}
}
La funcionalidad ya existe. La fachada slo se esconde. En este caso
hipottico, la LoggerManager controla la creacin del registrador correcta, y la
LoggerImpl es un objeto privado paquete que tiene el mtodo de "debug". De
esta manera la fachada no es la adicin de la funcionalidad que se acaba de
delegar en algunos de los objetos existentes.
En el otro lado el mediador agregar la nueva funcionalidad mediante la
combinacin de diferentes objetos.
Same Client code:

Logger logger = new Logger();

logger.initLogger("someLogger");
logger.debug("message");
Implementation:

class Logger {

private java.io.PrintStream out;


private java.net.Socket client;
private java.sql.Connection dbConnection;
private String loggerName;

public void initLogger( String loggerName ) {


this.loggerName = loggerName;
if ( loggerName == "someLogger" ) {
out = new PrintStream( new File("app.log"));
} else if ( loggerName == "serverLog" ) {
client = new Socket("127.0.0.1", 1234 );
} else if( loggerName == "dblog") {
dbConnection = Class.forName()... .
}

public void debug( String message ) {

if ( loggerName == "someLogger" ) {
out.println( message );
} else if ( loggerName == "serverLog" ) {

ObjectOutputStrewam oos =
new ObjectOutputStrewam( client.getOutputStream());
oos.writeObject( message );
} else if( loggerName == "dblog") {
Pstmt pstmt = dbConnection.prepareStatment( LOG_SQL );
pstmt.setParameter(1, message );
pstmt.executeUpdate();
dbConnection.commit();
}
}
}
En este cdigo, el mediador es el que contiene la lgica de negocio para crear
el "canal" para iniciar una sesin y tambin para hacer el registro en ese canal.
l es "crear" la funcionalidad.
Por supuesto, hay mejores formas de implementar esto usando polimorfismo,
pero el punto aqu es mostrar cmo el mediador "agrega" nueva funcionalidad
mediante la combinacin de la funcionalidad existente (en mi muestra no
mostr mucho lo siento), pero se imaginan el mediador, leen a partir de la base
de datos del host remoto para iniciar la sesin en donde, a continuacin, crea
un cliente y finalmente escribir en la impresora del cliente que transmitir los
mensajes de registro. De esta manera el mediador sera "mediar" entre los
diferentes objetos.
Por ltimo, la fachada es un patrn estructural, es decir que describe la
composicin de los objetos, mientras que el mediador es un comportamiento,
es decir, que describe la forma interactan los objetos.
2.15. Patrn Template Method

2.15.1.

Definicin

En ingeniera de software, el patrn de mtodo de la plantilla es


un patrn de diseo de comportamiento que define el esqueleto
de programa de un algoritmo en un mtodo, llamado mtodo de
plantilla, el cual difiere algunos pasos a las subclases. Permite
redefinir ciertos pasos seguros de un algoritmo sin cambiar la
estructura del algoritmo.

2.15.2.

Esquema

2.15.3.

Ejemplo General

abstract class Game {


/* Hook methods. Concrete implementation may differ in each subclass*/
protected int playersCount;
abstract void initializeGame();
abstract void makePlay(int player);
abstract boolean endOfGame();
abstract void printWinner();

/* A template method : */
public final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame();
int j = 0;

while (!endOfGame()) {
makePlay(j);
j = (j + 1) % playersCount;
}
printWinner();
}
}

//Now we can extend this class in order


//to implement actual games:

class Monopoly extends Game {

/* Implementation of necessary concrete methods */


void initializeGame() {
// Initialize players
// Initialize money
}
void makePlay(int player) {
// Process one turn of player
}
boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
void printWinner() {
// Display who won
}
/* Specific declarations for the Monopoly game. */

// ...
}

class Chess extends Game {

/* Implementation of necessary concrete methods */


void initializeGame() {
// Initialize players
// Put the pieces on the board
}
void makePlay(int player) {
// Process a turn for the player
}
boolean endOfGame() {
// Return true if in Checkmate or
// Stalemate has been reached
}
void printWinner() {
// Display the winning player
}
/* Specific declarations for the chess game. */

// ...
}

2.15.4.
DataParser.java

Ejemplo con acceso a BD

package org.arpit.javapostsforlearning;
abstract public class DataParser {
//Template method
//This method defines a generic structure for parsing data
public void parseDataAndGenerateOutput() {
readData();
processData();
writeData(); }
//This methods will be implemented by its subclass
abstract void readData();
abstract void processData();
//We have to write output in a CSV file so this step will be same for all subclasses
public void writeData() {
System.out.println('Output generated,writing to CSV'); }}
In below class,CSV specific steps are implement in this class

CSVDataParser.java
package org.arpit.javapostsforlearning;
public class CSVDataParser extends DataParser {
void readData() {
System.out.println('Reading data from csv file'); }
void processData() {
System.out.println('Looping through loaded csv file');

}}

In below class,database specific steps are implement in this class

DatabaseDataParser.java
package org.arpit.javapostsforlearning;

public class DatabaseDataParser extends DataParser {


void readData() {
System.out.println('Reading data from database');
}
void processData() {
System.out.println('Looping through datasets');

}}

TemplateMethodMain.java
package org.arpit.javapostsforlearning;
public class TemplateMethodMain {
public static void main(String[] args) {
CSVDataParser csvDataParser=new CSVDataParser();
csvDataParser.parseDataAndGenerateOutput();
System.out.println('**********************');
DatabaseDataParser databaseDataParser=new DatabaseDataParser();
databaseDataParser.parseDataAndGenerateOutput();
}
}
output:
Reading data from csv file
Looping through loaded csv file
Output generated,writing to CSV
**********************
Reading data from database
Looping through datasets
Output generated,writing to CSV

2.16. Patrn Visitor

2.16.1.

Definicin

La idea bsica es que se tiene un conjunto de clases elemento


que conforman la estructura de un objeto. Cada una de estas
clases elemento tiene un mtodo aceptar (accept()) que recibe al
objeto visitante (visitor) como argumento. El visitante es una
interfaz que tiene un mtodo visit diferente para cada clase
elemento; por tanto habr implementaciones de la interfaz visitor
de la forma: visitorClase1, visitorClase2... visitorClaseN. El
mtodo accept de una clase elemento llama al mtodo visit de su
clase. Clases concretas de un visitante pueden entonces ser
escritas para hacer una operacin en particular.

2.16.2.

Esquema

Visitante (Visitor)
Declara una operacin de visita para cada elemento concreto en
la estructura de objetos, que incluye el propio objeto visitado

Visitante Concreto (ConcreteVisitor1/2)


Implementa las operaciones del visitante y acumula resultados
como estado local

Elemento (Element)
Define una operacin Accept que toma un visitante como
argumento

Elemento Concreto (ConcreteElementA/B):

Implementa la operacin Accept

2.16.3. Ejemplo General


package expresion;
public abstract class Expresion {
abstract public void aceptar(VisitanteExpresion v);
}

package expresion;
public class Constante extends Expresion {
public Constante(int valor) { _valor = valor; }
public void aceptar(VisitanteExpresion v) { v.visitarConstante(this); }
int _valor;
}

package expresion;

public class Variable extends Expresion {


public Variable(String variable) { _variable = variable; }
public void aceptar(VisitanteExpresion v) { v.visitarVariable(this); }
String _variable;
}

package expresion;
public abstract class OpBinaria extends Expresion {
public OpBinaria(Expresion izq, Expresion der) { _izq = izq; _der = der; }
Expresion _izq, _der;
}
package expresion;
public class Suma extends OpBinaria {
public Suma(Expresion izq, Expresion der) { super(izq, der); }
public void aceptar(VisitanteExpresion v) { v.visitarSuma(this); }
}

package expresion;
public class Mult extends OpBinaria {
public Mult(Expresion izq, Expresion der) { super(izq, der); }
public void aceptar(VisitanteExpresion v) { v.visitarMult(this); }
}

/*
* Esta es la clase abstracta que define la interfaz de los visitantes
* de la jerarqua Expresion -- en realidad, utilizamos una interfaz Java
* dado que todos los mtodos son abstractos.
*/

package expresion;
public interface VisitanteExpresion {
public void visitarSuma(Suma s);
public void visitarMult(Mult m);
public void visitarVariable(Variable v);
public void visitarConstante(Constante c);
}

/**
* Uno de los posibles visitantes de las Expresiones es un pretty printer
* que convierte a cadena de caracteres la expresin aritmtica. El algoritmo
* usado no optimiza el uso de parntesis... El resultado se acumula en
* el atributo privado _resultado, pudindose acceder a ste desde el exterior
* mediante el mtodo obtenerResultado()
*/

package expresion;
public class PrettyPrinterExpresion implements VisitanteExpresion {

// visitar la variable en este caso es guardar en el resultado la variable


// asociada al objeto... Observe que accedemos al estado interno del objeto
// confiando en la visibilidad de paquete...

public void visitarVariable(Variable v) {


_resultado = v._variable;
}

public void visitarConstante(Constante c) {


_resultado = String.valueOf(c._valor);

// Dado que el pretty-printer de una operacin binaria es casi idntica,


// puedo factorizar parte del cdigo con este mtodo privado...

private void visitarOpBinaria(OpBinaria op, String pOperacion) {


op._izq.aceptar(this);
String pIzq = obtenerResultado();

op._der.aceptar(this);
String pDer = obtenerResultado();

_resultado = "(" + pIzq + pOperacion + pDer + ")";


}

// Por ltimo la visita de la suma y la mult se resuelve mediante el mtodo


// privado que se acaba de mencionar...

public void visitarSuma(Suma s) {


visitarOpBinaria(s, "+");
}
public void visitarMult(Mult m) {
visitarOpBinaria(m, "*");
}

// El resultado se almacena en un String privado. Se proporciona un mtodo


// de acceso pblico para que los clientes del visitante puedan acceder
// al resultado de la visita

public String obtenerResultado() {


return _resultado;
}
private String _resultado;
}

import expresion.*;
class Main {
static public void main(String argv[]) {
// Construccin de una expresin (a+5)*(b+1)
Expresion expresion = new Mult( new Suma( new Variable("a"),
new Constante(5) ),
new Suma( new Variable("b"),
new Constante(1) ));

// Pretty-printing...
PrettyPrinterExpresion pretty = new PrettyPrinterExpresion();
expresion.aceptar(pretty);

// Visualizacion de resultados
System.out.println("Resultado: " + pretty.obtenerResultado());
}
}

2.16.4.

Ejemplo con acceso a BD

As que por la intuicin, el paso 1 sera la siguiente


interface QueryPart {
String getSQL();

// Que las variables se unen a un preparado QueryPart


// Declaracin, dada la siguiente ndice se unen, volviendo
// El ltimo ndice se unen int bind(PreparedStatement statement, int
nextIndex);
}
Con esta API, podemos fcilmente resumen de una consulta SQL y delegar las
responsabilidades a los objetos de nivel inferior. Un BetweenCondition por
ejemplo. Se ocupa de ordenar correctamente las partes de un [campo] Entre
[baja] condicin AND [superior], lo que hace SQL sintcticamente correcta,
piezas de delegacin de las tareas a sus nios-QueryParts:
class BetweenCondition {
Field field;
Field lower;
Field upper;

public String getSQL() {


return field.getSQL() + " between " +
lower.getSQL() + " and " +
upper.getSQL();
}

public int bind(PreparedStatement statement, int nextIndex) {


int result = nextIndex;

result = field.bind(statement, result);


result = lower.bind(statement, result);
result = upper.bind(statement, result);

return result;
}

}
Mientras que bindValue por el contrario, sera principalmente cuidar de enlace
variable

class BindValue {
Object value;
public String getSQL() {
return "?";
}
public int bind(PreparedStatement statement, int nextIndex) {
statement.setObject(nextIndex, value);
return nextIndex + 1;
}
}
En combinacin, ahora podemos crear fcilmente las condiciones de esta
forma:? ENTRE ? Y?. Cuando se implementan ms QueryParts, tambin
podramos imaginar cosas como MY_TABLE.MY_FIELD ENTRE? Y (SELECT?
FROM DUAL), cuando las implementaciones de campo apropiados estn
disponibles. Eso es lo que hace que el patrn compuesto tan potente, una API
comn y muchos componentes que encapsulan el comportamiento, delegando
partes del comportamiento de los subcomponentes.
Paso 2 se ocupa de la evolucin de la API

El patrn de material compuesto que hemos visto hasta ahora es bastante


intuitiva, ya la vez muy poderosa. Pero tarde o temprano, necesitaremos ms
parmetros, como nos damos cuenta que queremos pasar del estado de
QueryParts matrices a sus hijos. Por ejemplo, queremos ser capaces de inline
algunos valores se unen para algunas clusulas. Tal vez, algunos dialectos
SQL no permiten valores vinculados en la clusula BETWEEN. Cmo manejar
eso con la API actual? Ampliarlo, aadiendo un parmetro "booleano en lnea"?
No! Esa es una de las razones por las cuales el visitor fue inventado. Para
mantener la API de los elementos de estructura compuesta simples (slo tienen
que aplicar "aceptar"). Pero en este caso, mucho mejor que la implementacin
de un verdadero patrn de visitante es reemplazar los parmetros de un
"contexto":
interface QueryPart {

void toSQL(RenderContext context);


void bind(BindContext context);
}
interface RenderContext {
boolean inline();
RenderContext inline(boolean inline);
boolean declareFields();
RenderContext declareFields(boolean declare);
boolean declareTables();
RenderContext declareTables(boolean declare);
boolean cast();
RenderContext sql(String sql);
RenderContext sql(char sql);
RenderContext keyword(String keyword);
RenderContext literal(String literal);
RenderContext sql(QueryPart sql);
}
Lo mismo ocurre con la BindContext. Como se puede ver, es muy extensible,
nuevas propiedades se pueden aadir a esta API, otros medios comunes de
prestacin de SQL se puede aadir, tambin. Pero el BetweenCondition no
tiene que renunciar a su conocimiento encapsulado acerca de cmo hacer que
su SQL, y si las variables se unen se les permite o no. Se va a mantener que el
conocimiento de s mismo:
class BetweenCondition {
Field field;
Field lower;
Field upper;
public void toSQL(RenderContext context) {
context.sql(field).keyword(" between ")
.sql(lower).keyword(" and ")
.sql(upper);

}
public void bind(BindContext context) {
context.bind(field).bind(lower).bind(upper);
}
}
class BindValue {
Object value;

public void toSQL(RenderContext context) {


context.sql("?");
}
public void bind(BindContext context) {
context.statement().setObject(context.nextIndex(), value);
}
}

Вам также может понравиться