Anda di halaman 1dari 24

El patrn Estrategia

Fecha de la ltima revisin: 21.05.2014


Revisin 3.0 (21.05.2014)
Miguel ngel Abin
1. Introduccin
En este artculo se expone el patrn Estrategia desde dos puntos de vista: el terico y el prctico. Por un lado, se explican los argumentos
tericos para usar este patrn; por otro, se dan algunos consejos para saber cundo conviene usarlo y se exponen tres ejemplos completos
de su uso en Java. Para seguir el artculo, no se necesita ningn conocimiento previo que no sea comprender, aun someramente, el
lenguaje Java.
Segn la ltima versin del diccionario de la Real Academia Espaola, un patrn es "el modelo que sirve de muestra para sacar otra cosa
igual". Aunque la definicin no usa ningn trmino informtico, se adecua bastante bien al sentido con que se emplea patrn en la
ingeniera del software. En esta disciplina, los patrones no son muestras fsicas o ejemplares a partir de los cuales se puedan construir cosas
iguales; sino representaciones abstractas que sirven para especificar y documentar soluciones recurrentes a ciertos problemas habituales.
Pese a lo mucho que se usan los patrones de software, no abundan las definiciones del trmino "patrn de software". Ms an: incluso el
creador del trmino patrn en el sentido de buena prctica (aplicado a la arquitectura, no a la construccin de software) pareca sentirse
ms cmodo escribiendo un libro voluminoso, abstracto y, a ratos, confuso que definiendo de forma clara y precisa el concepto de patrn.
Una definicin que no har mal a nadie es la que aparece en [1]:
[Un patrn] es una descripcin en un formato fijo de cmo resolver un cierto tipo de problemas.
Segn Brad Appleton (la definicin la le hace cuatro o cinco aos en http://www.enteract.com/~bradapp/docs/pattern-intro.html; la
direccin ya no funciona), un patrn es
[...] una unidad de informacin instructiva con nombre, la cual captura la estructura esencial y la compresin de una familia de soluciones
exitosas probadas para un problema recurrente que ocurre dentro de un cierto contexto y de un sistema de fuerzas.
La definicin ms completa que conozco para el trmino aparece en [2] y es obra de James Coplien:
Un patrn es una regla constituida por tres partes; la cual expresa una relacin entre un cierto contexto, un cierto sistema de fuerzas que
ocurren repetidamente en ese contexto y una cierta configuracin de software que permite a estas fuerzas resolverse a s mismas.
Segn esta definicin, tres son las partes fundamentales de un patrn: un sistema de fuerzas, un contexto y una configuracin de
software.
Sistema de fuerzas es el trmino que usa Coplien como generalizacin del tipo de criterios que usan los ingenieros de software y los
programadores para argumentar sus diseos e implementaciones. Cada vez que se disea o implementa un componente de software, las
fuerzas son los objetivos y restricciones que deben considerar ingenieros y programadores para el componente. Hallar una solucin de
software para un problema es solucionar el sistema de fuerzas asociado al problema. Una fuerza puede ser la velocidad de ejecucin, el
consumo de memoria RAM, la interoperabilidad con otros programas, la existencia de errores, etc.
La expresin configuracin de software es usada por Coplien para denotar cualquier conjunto de reglas de diseo susceptible de ser utilizado
para solucionar un sistema de fuerzas. Solucionar un sistema de fuerzas es encontrar un equilibrio ptimo entre las fuerzas que afectan al
sistema. Dependiendo de la naturaleza de las fuerzas, puede ser imposible demostrar formalmente que una solucin equilibra de forma
ptima (esto es, resuelve) un sistema de fuerzas. Por ejemplo, si una fuerza es el impacto social o poltico, no puede probarse
analticamente que una solucin es ptima (al menos, no con las tcnicas matemticas actuales).
Por ltimo, contexto es el entorno en que se enmarca un sistema de fuerzas. Un contexto dado puede hacer inservibles ciertas
configuraciones de software o hacer que unas sean preferible a otras.
En definitiva, la definicin de Coplien plantea que un patrn es una descripcin genrica de una solucin recurrente para un problema
recurrente condicionado por la consecucin de ciertos objetivos sujetos a ciertas restricciones.
El concepto de patrn en el sentido que usamos aqu procede del campo de la arquitectura: fue el arquitecto Christopher Alexander quien
primero manej el trmino, basndose en los temas recurrentes en el diseo de edificios y calles; ms tarde, la idea fue transplantada al
dominio del diseo de software. Cuando analiz la historia de la Arquitectura, Alexander encontr diseos y construcciones que se repetan
en zonas geogrficas muy alejadas y de culturas muy distintas. Por ejemplo, los tejados de las casas de los pueblos pequeos eran y son
muy similares (estn hechos de tejas, tienen una gran pendiente), aunque las necesidades de los habitantes han debido ser muy distintas
(stas dependen de factores geogrficos, climticos y personales). La persistencia de estos tejados es un indicio de que existe una solucin
ptima (un patrn) para la construccin de tejados que se ha venido copiando, con pequeas variaciones y quizs de forma inconsciente, en
muchos pueblos del mundo. Segn Alexander,
Cada patrn describe un problema que ocurre una y otra vez en nuestro ambiente y despus describe la parte ms importante de la
solucin a ese problema de tal manera que se pueda utilizar esta solucin un milln de veces, sin hacerlo dos veces de la misma manera.
En uno de sus libros [3], aparece como ejemplo de patrn de diseo arquitectnico el de las "Ventanas de la Calle", que reproduzco aqu.
Copyright (c) 2004-2014, Miguel ngel Abin. Este documento puede ser distribuido solo bajo los trminos y condiciones de la licencia de
Documentacin de javaHispano v1.0 o posterior (la ltima versin se encuentra en http://www.javahispano.org/licencias/).
Page 1 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Los patrones de software se pueden dividir en distintas categoras. En el libro [4], los patrones se clasifican en:
Patrones de diseo. Ofrecen esquemas para refinar subsistemas y componentes de un sistema de software, o las relaciones entre
ellos. Por lo general, describen una estructura de comunicacin recurrente entre componentes, que sirve para resolver un problema
general de diseo en un contexto determinado.
Patrones arquitectnicos. Expresan una organizacin estructural bsica para un sistema de software, organizacin referida a un
conjunto de subsistemas predefinidos. Asimismo, especifican las responsabilidades de estos subsistemas y proporcionan directrices y
reglas para organizar las relaciones entre ellos.
Patrones de implementacin (idioms). Estos patrones son de bajo nivel de abstraccin, pues estn asociados a lenguajes de
programacin concretos; describen cmo implementar ciertas caractersticas de los componentes de software o de sus relaciones
haciendo uso de las estructuras y propiedades de un lenguaje de programacin. Por ejemplo, en C++, el cdigo while (*destino++ =
*src++); es un patrn de implementacin para copiar cadenas de caracteres.
Segn la bibliografa tcnica, los patrones de diseo ofrecen las siguientes ventajas:
Facilitan la reutilizacin del diseo. Usando patrones de diseo, se pueden reusar diseos de software en tantas aplicaciones como se
quiera, aun cuando stas se escriban en distintos lenguajes de programacin.
Simplifican el proceso de diseo. Si en la fase de anlisis uno encuentra un problema para el cual existe un patrn de diseo, ya tiene
hecha ms de la mitad del trabajo: no necesita comenzar el diseo desde cero.
Facilitan la transmisin de los conocimientos adquiridos por otros programadores. Usando patrones de diseo, los programadores
nefitos pueden aprender rpidamente cmo piensan los diseadores expertos.
Proporcionan un vocabulario comn y consistente para el diseo de software. Esta caracterstica facilita la comunicacin entre
diseadores. Hablar de patrones es ms abstracto que hablar de clases o interfaces.
Acercan el desarrollo de software a lo que se espera de una ingeniera. El desarrollo de un vocabulario comn y de una lista de
buenas prcticas es comn a cualquier ingeniera.
Muestran buenos principios de diseo. Principios como el encapsulado, la abstraccin y la cohesin entran desde el principio en los
patrones de diseo.
Ayudan a comprender las bibliotecas de clases que los usan. Java, por ejemplo, tiene muchos paquetes que se han construido
basndose en patrones de diseo.
El libro ms influyente en cuanto a patrones de diseo en software es [5], que define patrn de diseo como "una descripcin de clases y
objetos que se comunican entre s, adaptada para resolver un problema de diseo general en un contexto particular". Es un libro nuevo,
pero no original: clasifica y organiza unas ideas que ya llevaban cierto tiempo en el aire. Debido a su popularidad y predicamento, este libro
es de lectura obligada para quien quiera asomarse al mundo de los patrones. En l se distinguen tres tipos de patrones de diseo para
software: patrones de creacin, de comportamiento y estructurales:
Patrones de creacin. Son patrones que abstraen el proceso de creacin de los objetos. Se dividen en patrones de creacin de
clases (el patrn Mtodo de fbricas -Factory Method-, por ejemplo) y de creacin de objetos (el patrn Constructor -Builder-, p. ej.).
Patrones de comportamiento. Estos patrones asignan responsabilidades y algoritmos a los objetos. Se dividen en patrones de
comportamiento de objetos (el patrn Observador -Observer-, por ejemplo) y de comportamiento de clases (el patrn Mtodo de
plantillas -Template Method-, p. ej.).
Figura 1. Un patrn de diseo arquitectnico: las ventanas de la calle. Una casa sin ventanas es fra y poco acogedora.
Asimismo, es desagradable estar en un casa que d a una calle sin ninguna ventana
Page 2 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Patrones estructurales. Son patrones que definen cmo deben combinarse las clases y los objetos para solucionar eficazmente
ciertos problemas. Se dividen en patrones estructurales de objetos (el patrn Adaptador -Adapter-, por ejemplo) y en patrones
estructurales de clases (el patrn en patrones estructurales de clases (el patrn Compuesto o Entidad compuesta -Composite-, p.
ej.).
En javaHispano existe una serie de artculos sobre patrones [6], obra de Alberto Molpeceres; as como un tutorial muy completo[7], obra de
Martn Prez. Si el lector desea conocer ms patrones, le recomiendo leer estos trabajos. El presente artculo es una acotacin marginal a
ellos.
2. El patrn Estrategia
Segn [5], el patrn Estrategia "define una familia de algoritmos, encapsula cada uno y los hace intercambiables. La Estrategia deja que el
algoritmo vare independientemente de los clientes que lo usen" (pgina 315).
Me he decidido a escribir sobre este patrn por varios motivos:
Es un patrn muy til para seguir el Principio Abierto/Cerrado ("Una entidad de software -clase, mdulo, etctera- debe estar abierta
para su extensin, pero cerrada para su modificacin").
Muestra el poder del polimorfismo en los lenguajes orientados a objetos.
Al basarse en el encapsulado y en la programacin de interfaces, constituye un buen ejemplo de la aplicacin de los principios del
diseo orientado a objetos.
En el principio Abierto/Cerrado, "debe estar abierta para su extensin" significa que no se ha de cambiar una clase existente cuando se
extiendan sus funciones; "cerrada para su modificacin" significa que deben existir subclases o clases abstractas o interfaces en las que
delegar las nuevas funciones que se desee aadir. Para que el principio Abierto/Cerrado no quede en mera palabrera o en una montaa de
buenas intenciones, se necesitan varios ingredientes: abstraccin, encapsulado, polimorfismo, herencia e interfaces. No por casualidad,
estas herramientas son el ncleo de la verdadera programacin orientada a objetos. Sin ellas, un programa escrito en Java, Smalltalk o
C++ sera tan orientado a objetos como meldico es el chirriar de una bisagra oxidada.
Para entender las implicaciones del principio Abierto/Cerrado, se puede considerar el siguiente cdigo, correspondiente a un mtodo que
calcula el importe total de la compra en un supermercado:
public double calcularImporteVenta(Producto productos[]) {
double importeTotal = 0.00;
for (i=0; i < productos.length; i++) {
importeTotal += producto[i] * getPrecio();
}
return importeTotal;
}

Tal y como est escrito el mtodo CalcularImporteVenta(), cumple perfectamente el principio Abierto/Cerrado. Consideremos ahora que la
inflacin se est disparando en el pas donde se encuentra el supermercado y que sus dueos, comprometidos con el bienestar del pas y
con los estrictos criterios macroeconmicos del Fondo Monetario Internacional, deciden rebajar el precio de los alimentos que ms influyen
sobre la inflacin: el pan y la carne de pollo. S, algo de irona hay en el ejemplo; pero no es irnico que una institucin de pases
industrializados proponga polticas y prcticas antiproteccionistas que ningn pas industrializado ha seguido nunca? En fin, el cdigo del
mtodo anterior quedara as:
public double calcularImporteVenta(Producto productos[]) {
double importeTotal = 0.00;
for (i=0; i < productos.length; i++) {
if (productos[i] instanceof BarraPan)
importeTotal += producto[i] * 0.85 * getPrecio();
else if (productos[i] instanceof Pollo)
importeTotal += producto[i] * 0.90 * getPrecio();
else
importeTotal += producto[i] * getPrecio();
}
return importeTotal;
}

Este cdigo ya no cumple el principio Abierto/Cerrado. Si la lista de productos alimentarios que influyen en la inflacin cambiara, habra que
aadir nuevos productos y eliminar otros. Se incumplira, pues, la condicin de cerrado para modificaciones. Tal como se ver en la seccin
4, el patrn Estrategia permite cumplir el principio.
La representacin UML del patrn Estrategia se muestra en la figura 2.
Page 3 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Las clases que aparecen en la figura se explican aqu:
Contexto. Un objeto Contexto es un cliente que usa una operacin de la interfaz ofrecida por EstrategiaAbstracta. Por tanto,
mantiene una referencia a un objeto que es instancia de alguna clase de las derivadas por herencia de la clase EstrategiaAbstracta.
Contexto desconoce qu clases implementarn la operacin o cmo lo harn.
EstrategiaAbstracta. Esta clase define el comportamiento fundamental de las clases Estrategia. Al ser una clase abstracta o una
interfaz (en Java o C#), no pueden crearse instancias de ella. Para realizar operaciones, los clientes deben usar instancias de sus
subclases concretas.
EstrategiaConcreta1, EstragegiaConcreta2, etc. Las instancias de estas clases especializan el comportamiento bsico
especificado por EstrategiaAbstracta. La especializacin se consigue mediante la implementacin de las operaciones de
EstrategiaAbstracta o la definicin de otras nuevas. Los objetos cliente tienen referencias a instancias de estas clases.
En Java, las subclases de EstrategiaAbstracta se derivan de sta mediante extends (si sta es una clase abstracta) o implements (si es una
interfaz). Existen situaciones sencillas en las que la clase EstrategiaAbstracta puede ser sustituida por una clase que implementa los
comportamientos deseados; en este caso, no se necesitan las clases EstrategiaConcreta1, EstragegiaConcreta2, etc. Al final de la siguiente
seccin se pondr un ejemplo de esta situacin, la cual correspondera a lo que puede denominarse "patrn Estrategia degenerado".
Cuando se aplica a un problema, el patrn Estrategia rompe el diseo en dos partes claramente diferenciadas: la del Contexto y la de la
Estrategia. La primera parte es la parte invariante del diseo, pues su comportamiento no cambia de vez en vez. La segunda (formada por
la clase EstrategiaAbstracta y sus subclases) aprehende la naturaleza cambiante y modificable del diseo: cada subclase de
EstrategiaConcreta define un comportamiento especfico que puede necesitarse cuando el programa est en ejecucin. En cierto modo, el
patrn Estrategia aprovecha el mecanismo de la herencia para sacar factor comn de los distintos algoritmos.
Existen varios modos de colaboracin entre la Estrategia y el Contexto que permiten elegir el comportamiento deseado en cada ocasin. Los
dos ms habituales se detallan aqu:
Un objeto Contexto puede pasar a un objeto Estrategia, cuando sea necesario, todos los datos necesarios para el mtodo que
implementa el comportamiento deseado. La gran ventaja de trabajar as radica en que se consigue desacoplar el Contexto de la
Estrategia.
Un Contexto puede pasar una referencia a s mismo como argumento de los mtodos que implementan las operaciones de la interfaz
de Estrategia. De este modo, la Estrategia puede llamar al Contexto cada vez que lo necesite. La desventaja de obrar as es que se
aumenta el acoplamiento entre Contexto y Estrategia.
Normalmente, los clientes que necesitan las operaciones de la Estrategia no acceden directamente a los mtodos que las implementan, sino
que interaccionan solamente con el Contexto (que, a su vez, es un cliente de la Estrategia). Los clientes crean y pasan objetos del tipo
EstrategiaConcreta a objetos Contexto, que se encargan de pasar las peticiones a la Estrategia.
3. Usos del patrn Estrategia
De modo general, resulta conveniente emplear el patrn Estrategia cuando los clientes implementan algoritmos genricos que son difciles
de reusar, de intercambiar y cuya eleccin puede variar en tiempo de ejecucin. Un buen indicio de lo anterior lo da la proliferacin
Figura 2. Estructura del patrn Estrategia
Page 4 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
cancerosa de expresiones condicionales en el cdigo (if, switch/case).
Por ejemplo, consideremos que se quiere escribir una aplicacin encargada de cifrar texto mediante claves. Dada una clave y un texto, la
aplicacin debe generar un texto indescifrable para cualquiera que no tenga la clave con la que se codific el texto. Consideremos tambin
que existen varias implementaciones para el algoritmo de cifrado. Los motivos para esta multiplicidad no son tericos: dependiendo de la
longitud del texto, puede haber implementaciones ms eficaces que otras, pueden existir implementaciones ms rpidas pero que
consuman ms recursos (memoria, espacio en el disco duro, etc.)...
Una solucin a nuestro problema sera colocar toda la lgica del negocio en la clase cliente (la que usa los algoritmos). Mediante sentencias
condicionales, el cdigo del cliente elegira el algoritmo de cifrado que necesitara. Esta solucin dista de ser idnea: segn se fueran
incorporando nuevas implementaciones del algoritmo, aumentara el nmero de sentencias condicionales y se necesitara modificar el cdigo
del cliente, as como recompilarlo. Aparte, sera imposible cifrar dinmicamente un texto mediante diferentes algoritmos.
Otra solucin consistira en escribir una clase general cuyas subclases encapsularan cada una de las implementaciones del algoritmo de
cifrado. Los problemas de esta otra solucin no seran despreciables: seguira siendo necesario mantener las sentencias condicionales, se
disparara el nmero de subclases y el comportamiento seguira fijado en tiempo de compilacin. Un objeto, pongamos por caso,
Implementacion1 no podra comportarse como un objeto Implementacion2 durante la ejecucin del programa: una vez creado, su
comportamiento sera inmodificable.
Para este problema, el patrn Estrategia proporciona una excelente solucin. Basta seguir estos pasos:
Identifquese el comportamiento deseado (cifrado del texto mediante una clave).
Especifquese la interfaz del comportamiento en una clase abstracta o en una interfaz (EstrategiaAbstracta).
Desplcese todo el cdigo basado en sentencias condicionales a cada una de las subclases concretas de EstrategiaAbstracta.
Cada vez que se necesite una implementacin concreta del algoritmo de cifrado, delguese la peticin a un objeto (Contexto) que
contenga referencias a objetos del tipo EstrategiaAbstracta.
Con el patrn Estrategia, cada vez que se necesita aadir nuevas implementaciones del algoritmo de cifrado, no se precisar modificar el
cliente ni el Contexto: slo habr que aadir una nueva clase EstrategiaConcreta. Como los clientes usan la interfaz de mtodos definida por
EstrategiaAbstracta (es decir, su tipo, no la clase), un mismo objeto Texto podr ser cifrado con todas las implementaciones.
Cundo conviene usar el patrn Estrategia?
Cuando hay muchas clases interrelacionadas que difieren solamente en comportamiento. Este patrn proporciona un modo de
configurar el comportamiento deseado sin modificar el tipo de cada objeto.
Cuando se necesitan distintas variantes de un mismo algoritmo.
Cuando un algoritmo usa datos que no queremos que sean visibles para los clientes. El patrn Estrategia permite evitar que los
clientes conozcan las estructuras de datos que se usen internamente.
He aqu algunas situaciones en las que se cumple una o varias de las condiciones expuestas arriba:
Representacin grfica de unos mismos datos en distintas formas (grfico de barras, de porciones, etc.).
Compresin de ficheros en distintos formatos (Zip, GZip, Rar, etc.).
Grabacin de ficheros en distintos formatos (HTML, PDF, Word, etc.).
Utilizacin de distintas polticas de seguridad en el acceso a los recursos de una red.
Encaminamiento de paquetes IP mediante diversos algoritmos (la eleccin depender del estado de las redes, del trficos de datos,
de la distancia entre redes, etc.).
Ordenacin o bsqueda de elementos en una coleccin por medio de distintos algoritmos (mtodo de la burbuja, bsqueda
secuencial, etc.)
4. Algunos ejemplos del patrn Estrategia
No necesitamos recurrir al software para ver ejemplos del patrn Estrategia. La propia realidad nos ofrece unos cuantos. Consideremos, por
ejemplo, una agencia de viajes; en la figura 3 se muestra su representacin UML.
Page 5 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Como es bien sabido, una agencia de viajes ofrece el servicio de proporcionar viajes a sus clientes. Mediante ella, una persona puede
seleccionar el viaje deseado (medio de transporte, precio, destino) entre los que la agencia pone a disposicin de los clientes. Segn el
patrn Estrategia, el cliente interacciona con la agencia de viajes para seleccionar el comportamiento deseado para su viaje.
El patrn Estrategia tambin puede usarse para plantear asuntos ms existenciales. Vivimos en una poca en que la adolescencia se
prolonga hasta los treinta, en que la juventud es el valor supremo y en que algunas empresas se jactan de que la media de edad de sus
plantillas no supera los treinta y cinco aos (empresas, por cierto, que omiten dar la edad media de sus directivos: si tanto importa la
juventud del personal, por qu no tienen directores y presidentes con menos de cincuenta aos?). El patrn Estrategia tambin sirve para
recordarnos el orden natural de las cosas:
Figura 3. Una agencia de viajes
Page 6 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Dependiendo de la edad de una persona, la Vida elige una especializacin de Persona (Nio, Adulto o Anciano). El patrn Estrategia permite
que estas especializaciones aadan sus propios comportamientos especializados al comportamiento base definido en Persona: trabajar(),
balbucear(), cobrarPension().
Si nos restringimos a la aplicacin del patrn Estrategia al software, podemos considerar el ejemplo que aparece en [5] (pgina 315),
consistente en un programa para dividir un texto en lneas (por ejemplo, con espaciado sencillo o doble). Gamma et al. razonan que resulta
desaconsejable escribir el cdigo de los algoritmos de insercin de saltos de lnea dentro de las clases que necesiten dichos algoritmos. Tres
son los motivos aducidos:
Los clientes se volveran ms complejos si incluyeran el cdigo de todos los algoritmos para colocar los saltos de lnea.
Sera difcil modificar los algoritmos existentes y aadir nuevos.
Algunos clientes tendran algoritmos para la insercin de saltos de lnea que raras veces, o nunca, usaran.
La solucin que proponen Gamma et al. consiste en aplicar el patrn Estrategia del modo representado en la figura 5.
En este ejemplo, la clase Composition mantiene una coleccin de instancias Component, que representan texto y elementos grficos en un
documento. Un objeto Composition organiza los objetos componentes dependiendo de la manera de insertar saltos de lnea que se adopte.
La clase Composition se encarga de mantener y actualizar los saltos de lnea del texto que se muestra en un visor de texto. Cada estrategia
para aplicar los saltos de lnea se implementa en subclases de la clase abstracta Compositor:
La clase SimpleCompositor implementa una estrategia simple que determina los saltos de lnea de uno en uno.
La clase TeXCompositor implementa el algoritmo TeX para encontrar saltos de lnea (se buscan y actualizan saltos de lnea prrafo a
prrafo).
Figura 4. La vida segun el patrn Estrategia
Figura 5. Ejemplo extrado del libro Design Patterns: Elements of Reusable Object-Oriented Software
Page 7 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
La clase ArrayCompositor implementa una estrategia que selecciona los saltos de lnea de modo que cada columna tenga un nmero
fijo de elementos.
Un objeto Composition (que representa un bloque de texto) mantiene una referencia a un objeto Compositor. Cuando un objeto
Composition vuelve a componer su texto, delega esta responsabilidad en el objeto Compositor asociado. Los clientes de Composition (un
procesador de textos, por ejemplo), especifican qu Compositor se usar eligiendo el objeto Compositor al cual se har referencia dentro del
Composition.
Otro ejemplo de uso del patrn Estrategia nos lo proporciona el paquete java.awt. Las instancias de la clase Component del AWT declaran
las instancias de la clase Contexto que permiten seleccionar y establecer distintos algoritmos de distribucin de los componentes grficos
mediante el mtodo SetLayout() de la interfaz LayoutManager (la clase EstrategiaAbstracta para este ejemplo), encargada de distribuir los
componentes grficos en el componente AWT. Las subclases de LayoutManager (BorderLayout, BoxLayout, FlowLayout, ScrollPaneLayout,
etc.) encapsulan su propia implementacin de setLayout().
Si consideramos la aplicacin de la seccin anterior que se encargaba de cifrar texto mediante claves, el patrn Estrategia nos dara una
solucin como la que se representa en la figura:
Figura 6. El patrn Estrategia en el AWT
Page 8 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Sin el patrn Estrategia, la implementacin del programa de codificacin de textos tendra un mtodo similar a ste:
public void cifrar(String clave, String bloqueTexto, int algoritmo) {
// Mtodo de la clase Texto, que representa textos que van a codificarse.
if (algoritmo == ALGORITMO_X)
CifrarConAlgoritmoX(clave, bloqueTexto);
if (algoritmo == ALGORITMO_y)
CifrarConAlgoritmoY(clave, bloqueTexto);
...
}

Con el patrn Estrategia, el mtodo quedara as:
public setAlgoritmoCifrado(Cifrado cifrado) {
// Mtodo de la clase Texto, que representa textos que van a cifrarse.
// Se escoge el algoritmo de cifrado en tiempo de ejecucin.
this.cifrado = cifrado;
}

public void cifrar(String clave, String bloqueTexto) {
// Mtodo de la clase Texto, que representa textos que van a cifrarse.
cifrado.codificar(clave, bloqueTexto);
}

Cualquier videojuego donde se pueda seleccionar un personaje segn la etapa del juego, el entorno, las caractersticas de los enemigos,
etc., es un buen ejemplo del patrn Estrategia. El cliente que elige, dependiendo de las condiciones, un personaje dado est eligiendo una
estrategia concreta, que hereda de una estrategia abstracta, con mtodos bsicos y comunes para todas sus subclases. Los programadores
de un videojuego no programan diferentes algoritmos de localizacin de los objetos y de representacin grfica de los mismos. Dicho de
otro modo: la manera de dibujar los pxeles de un ogro o de una encantadora dama no vara, ni tampoco varan los algoritmos generales
como los de deteccin de colisiones, etc. Todos los personajes tienen los mismos. Ahora bien, dependiendo del personaje, cambian los
pxeles que lo representan, as como el comportamiento frente a los ataques del enemigo, la resistencia, la habilidad con ciertas armas, etc.
Esos comportamientos especficos se definen en las estrategias concretas, mientras que en la estrategia abstracta se definen los
comportamientos generales.
En la figura 8 se muestra el patrn Estrategia para un videojuego donde el jugador puede elegir un personaje humano, leonino o batracio.
Cada Estrategia concreta (Humano, Leon, Batracio) tendr su propia implementacin de los mtodos luchar(arma, energia, duracionAtaque)
y huir (velocidadHuida), pues es de suponer que una rana no huir con la misma gracia y velocidad que un len; pero las tres subclases
recurriran a los mtodos de la superclase Personaje para mtodos como dibujarPixel(x, y), borrarPixel(x, y), MoverPixel(x_inic, y_inic,
x_dest, y_dest), etc.
Figura 7. El patrn Estrategia en el ejemplo de cifrado
Page 9 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Por ltimo, otro ejemplo de la aplicacin del patrn Estrategia lo proporciona el ejemplo de los productos de un supermercado que se vio en
la seccin 2. En lugar del cdigo que no cumple el principio Abierto/Cerrado, el patrn permite escribir este cdigo:
public class Producto {
private String nombre;
private double precio;
private Descuento descuento;

public Producto(String nombre) {
this.nombre = nombre;
}
public void setDescuento(Descuento descuento) {
this.descuento = descuento;
}
public void setPrecio(double precio) {
this.precio = precio;
}
public double getPrecio() {
return descuento.getPrecio(precio);
}
}

public class Descuento {
private double factor; //factor de descuento

public Descuento(double factor) {
this.factor = factor;
}
public double getPrecio(double precio) {
return precio * factor;
}
}

En este ejemplo, la clase EstrategiaAbstracta es una clase que implementa directamente sus mtodos (es decir, no es abstracta ni una
interfaz); en consecuencia, son innecesarias sus subclases. Con esta solucin se puede cambiar dinmicamente los descuentos de cualquier
producto del supermercado, sin modificar el cdigo ya escrito. Por ejemplo, si se quiere fijar el descuento del pollo en un 10%, bastar
escribir:
Producto pollo = new Producto("pollo");
pollo.setPrecio(30.05);
Figura 8. El patrn Estrategia en un videojuego
Page 10 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
pollo.setDescuento(new Descuento(0.90));

A la vista del cdigo de las dos ltimas clases, se puede formular lo que se conoce como un corolario del principio Abierto/Cerrado: "Si un
sistema de software debe permitir un conjunto de alternativas, lo ideal es que una sola clase en el sistema conozca el conjunto completo de
alternativas".
5. Tres ejemplos de implementacin en Java del patrn Estrategia
En esta seccin se exponen de forma completa tres ejemplos de uso del patrn Estrategia con Java. Los dos primeros son versiones
simplificadas de situaciones ante las que me he encontrado en mi actividad profesional. Son, pues, aplicaciones completamente prcticas del
patrn. Innegable es que usar este patrn exige un poco de reflexin y planificacin previas; pero creo que merece la pena: uno ahorra
mucho tiempo cuando tiene que introducir cambios o mejoras. Y no hay que engaarse: los clientes siempre piden mejoras, modificaciones o
refinamientos para sus aplicaciones (est en su naturaleza). Anticiparse a esos cambios de manera que se modifique lo menos posible el
cdigo o los mdulos ya escritos suele ser una buena prctica (al menos, si uno no cobra por horas de trabajo).
El tercer ejemplo se aleja mucho del mundo empresarial: consiste en usar el patrn Estrategia para modelar osciladores amortiguados
clsicos (no cunticos). Aparte de para estudiar muelles y resortes, los osciladores amortiguados son muy tiles para analizar estructuras
peridicas de tomos o molculas. De hecho, el ejemplo se me ocurri cuando analizaba los modos de vibracin de una red de difraccin
tridimensional.
5.1. Un programa de clculo de precios con descuentos
Consideremos que se nos encarga una aplicacin de contabilidad para una tienda de muebles que clasifica sus productos en tres tipos:
mueble clsico, mueble kit y mueble de diseo. Dependiendo del tipo de mueble, la tienda hace un descuento por cada venta: mueble clsico,
un 5%; mueble kit, un 10%; y mueble moderno, un 15%.
Supongamos tambin que desconocemos el patrn Estrategia y que somos novatos en la programacin orientada a objetos. Entonces,
nuestro primer intento sera algo como (omito los mtodos get y set que no voy a usar y casi todos los comentarios):
package mobiliario;

/**
* Intento sin el patrn Estrategia: clase Mueble.
* Representa un mueble del catlogo de la tienda.
*
*/

public class Mueble {

private double precio; // Precio del catlogo.
private String codigo; // Cdigo en el catlogo.
private int tipo; // Tipo de mueble: clsico, kit o moderno.

public static final int CLASICO = 0;
public static final int KIT = 1;
public static final int MODERNO = 2;

public double getPrecio() {
return precio;
}

public String getCodigo() {
return codigo;
}

public int getTipo() {
return tipo;
}

public Mueble(String codigo, double precio, int tipo) throws ExcepcionTipoMueble {
if ( (tipo > Mueble.MODERNO) || (Mueble.CLASICO > tipo) )
throw new ExcepcionTipoMueble();
else {
this.codigo = codigo;
this.precio = precio;
this.tipo = tipo;
}
}

}

package mobiliario;

/**
* Intento sin el patrn Estrategia: clase VentaMueble.
* Esta clase representa la venta de un mueble del catlogo de la tienda
*/

import java.util.*;

public class VentaMueble {

private Date fecha; // Fecha de la venta.
private Mueble mueble; // Mueble que se vende.

Page 11 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
public Date getFecha() {
return fecha;
}

public VentaMueble(Mueble mueble){
fecha = new Date();
this.mueble = mueble;
}

public double calcularPrecioVenta() throws ExcepcionTipoMueble {
// El precio de venta tiene un descuento con respecto al del catlago.
if (mueble.getTipo()==Mueble.CLASICO){
return (mueble.getPrecio())*0.95;
}
else if (mueble.getTipo()==Mueble.KIT){
return (mueble.getPrecio())*0.90;
}
else if (mueble.getTipo()==Mueble.MODERNO){
return (mueble.getPrecio())*0.85;
}
else
throw new ExcepcionTipoMueble();
}

// Ejemplo de funcionamiento del programa.
public static void main(String args[]) throws ExcepcionTipoMueble {
VentaMueble vm = new VentaMueble (new Mueble("Sof Dal", 1800.65, Mueble.MODERNO));
System.out.println("Precio de venta: " + vm.calcularPrecioVenta());
}

}

package mobiliario;

/**
* Intento sin el patrn Estrategia: clase ExceptionTipoMueble.
* Esta excepcin se lanza cuando se introduce un tipo de mueble invlido.
*
*/

public class ExcepcionTipoMueble extends Exception {

public ExcepcionTipoMueble() {
super("Compruebe el tipo de mueble introducido.");
}

}

Los problemas de introducir toda la lgica del negocio en el cdigo del cliente ya se vieron, de modo general, en la seccin 3. En este
ejemplo, los problemas concretos son dos:
Si se introdujera un nuevo tipo de mueble en el catlogo de la tienda, habra que modificar el cdigo del cliente.
Si se cambiaran los descuentos (por ejemplo, en poca de rebajas), habra que modificar el cdigo del cliente. El cliente est
fuertemente acoplado con la poltica de descuentos.
Nuestra primera solucin es muy inestable: mnimos cambios llevan a reprogramar el cliente y a recompilarlo. Si utilizamos el patrn
Estrategia, obtendramos una solucin similar a sta (vuelvo a omitir los mtodos get y set que no voy a usar y casi todos los comentarios):
package mobiliario;

/**
* Interfaz Descuento (Solucin con el patrn Estrategia).
* Esta interfaz es la estrategia abstracta.
*/

public interface Descuento {

public double calcularPrecioVenta(double precio);

}

package mobiliario;

/**
* Interfaz DescuentoMuebleClasico (Solucin con el patrn Estrategia).
* Esta clase es una de las estrategias concretas.
*/

public class DescuentoMuebleClasico implements Descuento {
// Constructor
public DescuentoMuebleClasico() {
}
// Devuelve el precio con el descuento.
public double calcularPrecioVenta(double precio) {
return (precio * 0.95);
}

Page 12 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
}

package mobiliario;

/**
* Interfaz DescuentoMuebleKit (Solucin con el patrn Estrategia).
* Esta clase es una de las estrategias concretas.
*/

public class DescuentoMuebleKit implements Descuento {
// Constructor
public DescuentoMuebleKit() {
}
// Devuelve el precio con el descuento.
public double calcularPrecioVenta(double precio) {
return (precio * 0.90);
}
}

package mobiliario;

/**
* La interfaz DescuentoMuebleModerno (Solucin con el patrn Estrategia).
* Esta clase es una de las estrategias concretas.
*/

public class DescuentoMuebleModerno implements Descuento {
// Constructor
public DescuentoMuebleModerno() {
}
// Devuelve el precio con el descuento.
public double calcularPrecioVenta(double precio) {
return (precio * 0.85);
}

}

package mobiliario;

/**
* Clase Mueble (solucin con el patrn Estrategia).
* Representa un mueble del catlogo de la tienda.
* Esta clase es el contexto.
*/

public class Mueble {

private String codigo; // Cdigo en el catlogo.
private double precio; // Precio del catlogo.
private Descuento desc; // Tipo de descuento.

public double getPrecio() {
return precio;
}

public String getCodigo() {
return codigo;
}

public Descuento getDescuento() {
return desc;
}

public Mueble(String codigo, double precio, Descuento desc) throws Exception {
if ( (desc == null) ) {
// Cuando se crea un objeto Mueble, es obligatorio introducir su descuento.
throw new Exception("Debe introducir un tipo de descuento");
}
else {
this.codigo = codigo;
this.precio = precio;
this.desc = desc;
}
}

}

package mobiliario;

/**
* Clase VentaMueble (solucin con el patrn Estrategia).
* Esta clase representa la venta de un mueble del catlogo de la tienda.
* Es cliente de la clase Mueble (el contexto para este caso).
*/

import java.util.*;
Page 13 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...

public class VentaMueble {

private Date fecha; // Fecha de la venta.
private Mueble mueble; // Mueble vendido.

public Date getFecha() {
return fecha;
}

public VentaMueble(Mueble mueble){
this.fecha = new Date();
this.mueble = mueble;
}

public double calcularPrecioVenta() throws Excepcion {
return (mueble.getDescuento().calcularPrecioVenta(mueble.getPrecio()));
}

// Ejemplo de funcionamiento del programa.
public static void main(String[] args) throws Exception {
Mueble m = new Mueble ("Silla Luis XVI", 1300.67, new DescuentoMuebleClasico());
VentaMueble vm = new VentaMueble (m);
System.out.println ("Cdigo: " + m.getCodigo());
System.out.println("Precio de catlogo: " + m.getPrecio());
System.out.println("Precio de venta: " + vm.calcularPrecioVenta());
}

}

La segunda solucin presenta ventajas significativas con respecto a la primera: ahora podemos aadir nuevos tipos de descuento sin
modificar la clase Mueble ni la clase VentaMueble. Si se quiere incluir un nuevo descuento, basta aadir una nueva clase que implemente la
interfaz Descuento.
En el caso de que se desee optar por una poltica de descuentos personalizada para cada mueble, el patrn Estrategia permite escribir una
solucin como sta:
package mobiliario;

/**
* Clase Descuento (Solucin con el patrn Estrategia para el caso de polticas personalizadas
* de descuentos).
*/
public class Descuento {

private double factorDescuento; // Factor de descuento.

public Descuento (double factorDescuento) {
this.factorDescuento = factorDescuento;
}
public double calcularPrecioVenta(double precio) {
return (factorDescuento * precio);
}

}

package mobiliario;

/**
* Clase Mueble (solucin con el patrn Estrategia para el caso de polticas personalizadas
* de descuentos).
*/

public class Mueble {

private String codigo; // Cdigo en el catlogo.
private double precio; // Precio del catlogo.
private Descuento desc; // Tipo de descuento.

public double getPrecio() {
return precio;
}

public String getCodigo() {
return codigo;
}

public Descuento getDescuento() {
return desc;
}

public Mueble(String codigo, double precio, Descuento desc) throws Exception {
if ( (desc == null) ) {
// Cuando se crea un objeto Mueble, es obligatorio introducir su descuento.
throw new Exception("Debe introducir un tipo de descuento");
}
else {
this.codigo = codigo;
this.precio = precio;
Page 14 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
this.desc = desc;
}
}

}

package mobiliario;

/**
* Clase VentaMueble (solucin con el patrn Estrategia para el caso de polticas personalizadas
* de descuentos).
*/

import java.util.*;

public class VentaMueble {

private Date fecha; // Fecha de la venta.
private Mueble mueble; // Mueble vendido.

public Date getFecha() {
return fecha;
}

public VentaMueble(Mueble mueble){
this.fecha = new Date();
this.mueble = mueble;
}

public double calcularPrecioVenta() throws Exception {
return (mueble.getDescuento().calcularPrecioVenta(mueble.getPrecio()));
}

// Ejemplo de funcionamiento del programa.
public static void main(String[] args) throws Exception {
Mueble m = new Mueble ("Silla Barcelona", 4560.18, new Descuento(0.90));
VentaMueble vm = new VentaMueble (m);
System.out.println ("Cdigo: " + m.getCodigo());
System.out.println("Precio de catlogo: " + m.getPrecio());
System.out.println("Precio de venta: " + vm.calcularPrecioVenta());
}

}

5.2. Un programa de clculo de amortizaciones
Consideremos ahora que estamos trabajando en un mdulo de software para llevar la contabilidad de una empresa y que hemos llegado a la
parte del clculo de amortizaciones de los bienes de la empresa (mquinas, ordenadores, mobiliario, mercancas, etc.). Segn el Plan General
Contable, la amortizacin es "la expresin de la depreciacin sistemtica, anual y efectiva sufrida por el inmovilizado inmaterial y material por
su incorporacin al sistema productivo".
En principio, la Hacienda espaola admite varias maneras de calcular la amortizacin: la amortizacin mediante tablas, la amortizacin lineal,
la amortizacin degresiva por suma de dgitos y la amortizacin degresiva en progresin decreciente. Consideremos tambin que la empresa
para la cual trabajamos slo emplea los tres ltimos tipos de clculo. Lgicamente, los contables de la empresa desearn poder elegir el
clculo de amortizacin que haga mxima, para cada bien, la amortizacin; as podrn pagar menos a la Hacienda pblica.
El patrn Estrategia parece un buen candidato para echarnos una mano en el diseo de la parte de las amortizaciones: contamos con un
comportamiento abstracto (algo as como Amortizacion) que se particulariza en comportamientos concretos (AmortizacionDegresivaDigitos,
AmortizacionLineal, AmortizacionProgresionDecreciente).
Veamos una posible forma de implementar el clculo de amortizaciones con el patrn Estrategia (incorporo documentacin javadoc al
cdigo):
package amortizacion;

/**
* Esta interfaz es la estrategia abstracta del patron Estrategia.
*
*/

public interface Amortizacion {
/**
*
* @param precio Precio del bien.
* @param valorResidual Valor del bien al final de su vida til.
* @param vida Aos de vida til del bien.
* @param anyo Anualidad para la cual se quiere calcular la amortizacin del bien.
* @return Amortizacin correspondiente al ao anyo.
* @throws Excepcion
*/
public double calcularAmortizacion (double precio, double valorResidual, int vida, int anyo) throws Excepcion;
}

package amortizacion;

Page 15 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
/**
* AmortizacionLineal es una estrategia concreta del patrn Estrategia.
* Implementa el clculo de la amortizacin lineal (cuotas fijas).
*/

public class AmortizacionLineal implements Amortizacion {
/**
*
* @param precio Precio del bien.
* @param valorResidual Valor del bien al final de su vida til.
* @param vida Aos de vida til del bien.
* @param anyo Anualidad para la cual se quiere calcular la amortizacin del bien.
* @return Amortizacin correspondiente al ao anyo.
* @throws Excepcion
*/
public double calcularAmortizacion (double precio, double valorResidual, int vida, int anyo) throws Excepcion {
// Comprobacin de los argumentos
if ( (precio > 0) && (anyo > 0) && (vida > 0) && (vida >= anyo) && (valorResidual < precio) ) {
return ( (precio - valorResidual) / vida );
} else
throw new Excepcion();
}

/**
* Constructor sin argumentos.
*/
public AmortizacionLineal() {
}

}

package amortizacion;

/**
* AmortizacionDegresivaDigitos es una estrategia concreta del patrn Estrategia.
* Implementa el clculo de la amortizacin degresiva por suma de dgitos.
*/

public class AmortizacionDegresivaDigitos implements Amortizacion {
/**
*
* @param precio Precio del bien.
* @param valorResidual Valor del bien al final de su vida til.
* @param vida Aos de vida til del bien.
* @param anyo Anualidad para la cual se quiere calcular la amortizacin del bien.
* @return Amortizacin correspondiente al ao anyo.
* @throws Excepcion
*/

public double calcularAmortizacion (double precio, double valorResidual, int vida, int anyo) throws Excepcion {
// Comprobacin de los argumentos
if ( (precio > 0) && (anyo > 0) && (vida > 0) && (vida >= anyo) && (valorResidual < precio) ) {
return ( (precio - valorResidual) * ( (vida - anyo + 1.0) / ( (vida * (vida + 1)) / 2.0) ) );
} else
throw new Excepcion();
}

/**
* Constructor sin argumentos.
*/
public AmortizacionDegresivaDigitos() {
}

}

package amortizacion;

/**
* AmortizacionProgresionDecreciente es una estrategia concreta del patrn Estrategia.
* Implementa el clculo de la amortizacin degresiva en progresin decreciente.
*/

class AmortizacionProgresionDecreciente implements Amortizacion {
/**
*
* @param precio Precio del bien.
* @param valorResidual Valor del bien al final de su vida til.
* @param vida Aos de vida til del bien.
* @param anyo Anualidad para la cual se quiere calcular la amortizacin del bien.
* @return Amortizacin correspondiente al ao anyo.
* @throws Excepcion
*/
public double calcularAmortizacion (double precio, double valorResidual, int vida, int anyo) throws Excepcion {
// Comprobacin de los argumentos
if ( (precio > 0) && (anyo > 0) && (vida > 0) && (vida >= anyo) && (valorResidual < precio) ) {
double a = valorResidual / precio;
double b = (1./vida);
double t = (1. - Math.pow(a, b));
return ( precio * t * Math.pow((1 - t), anyo - 1) );
} else
Page 16 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
throw new Excepcion();
}

/**
* Constructor sin argumentos.
*/
public AmortizacionProgresionDecreciente() {
}

}

package amortizacion;

public class Excepcion extends Exception {

public Excepcion() {
super("Compruebe los valores introducidos en los parametros.");
}

}

package amortizacion;

/**
* Esta clase es el contexto del patrn Estrategia.
*/

public class Bien {
/**
* Precio del bien.
*/
private double precio;
/**
* Valor del bien al final de su vida til.
*/
private double valorResidual;
/**
* Aos de vida til del bien.
*/
private int vida;
/**
* Estrategia de amortizacin.
*/
private Amortizacion amortizacion;

/**
* Mtodo set para precio.
* @param precio Precio del bien.
*/
public void setPrecio(double precio) {
this.precio = precio;
}

/**
* Mtodo get para valorResidual.
* @return Valor residual del bien.
*/
public double getValorResidual() {
return valorResidual;
}

/**
* Mtodo set para valorResidual.
*
* @param valorResidual double
*/
public void setValorResidual(double valorResidual) {
this.valorResidual = valorResidual;
}

/**
* Mtodo get para precio
* @return Precio del bien
*/
public double getPrecio() {
return precio;
}

/**
* Mtodo set para vida.
*
* @param vida Aos de vida til del bien.
*/
public void setVida(int vida) {
this.vida = vida;
}

/**
* Mtodo get para vida.
* @return Aos de vida til del bien.
Page 17 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
*/
public int getVida() {
return vida;
}

/**
* Mtodo set para Amortizacion.
*
* @param amort Estrategia de amortizacion
*/
public void setAmortizacion(Amortizacion amort) {
this.amortizacion = amort;
}

/**
* Constructor
*
* @param precio Precio del bien.
* @param valorResidual Valor residual del bien.
* @param vida Vida til del bien.
* @param amort Estrategia de amortizacin.
*/
public Bien(double precio, double valorResidual, int vida, Amortizacion amort) {
this.precio = precio;
this.valorResidual = valorResidual;
this.vida = vida;
if (amort == null) {
this.amortizacion = new AmortizacionLineal();
} else
this.amortizacion = amort;
}

public void CambiarTipoAmortizacion (Amortizacion amort) {
if (amort != null)
setAmortizacion(amort);
}

public void calcularAmortizacion(int anyo) throws Excepcion {
System.out.println(amortizacion.calcularAmortizacion(precio, valorResidual, vida, anyo));
}

}

package amortizacion;

/**
* Esta clase es cliente de la clase Bien.
*
*/

public class Cliente {
// Ejemplo de uso del programa. Se calculan la amortizaciones al segundo ao.
public static void main(String args[]) {
try {
Bien bien = new Bien(60000., 5000., 10, null);
bien.calcularAmortizacion(2);
bien.CambiarTipoAmortizacion(new AmortizacionProgresionDecreciente());
bien.calcularAmortizacion(2);
bien.CambiarTipoAmortizacion(new AmortizacionDegresivaDigitos());
bien.calcularAmortizacion(2);
}
catch (Exception e) {
e.printStackTrace();
}
}

}

5.3. Un programa de clculo de posiciones para osciladores amortiguados.
En el mundo fsico hay muchos movimientos que son oscilatorios. El movimiento oscilatorio ms sencillo es el denominado movimiento
armnico simple. Cualquier sistema que experimente una fuerza restauradora lineal es candidato a ser considerado un oscilador armnico
simple. La ecuacin de movimiento para un oscilador armnico simple que oscila en una sola direccin es (k es la constante elstica del
oscilador)
O dicho de otra manera:
La solucin a la ecuacin diferencial de segundo grado es la siguiente:
Page 18 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
Donde A y el ngulo phi son constantes que se determinan al especificar unas condiciones iniciales (en Matemticas se suelen llamar
condiciones de contorno).
En cualquier sistema oscilatorio real existen fuerzas de friccin que tienden a provocar que el movimiento se detenga al cabo de un tiempo
(este tipo de movimiento se conoce como movimiento armnico amortiguado). La ecuacin general para un oscilador armnico amortiguado
es (lambda es la constante de amortiguacin del oscilador)
O lo que es lo mismo:
Esta ecuacin diferencial admite tres clases de soluciones:
1) Solucin amortiguada (cuando gamma es menor que omega0)
La solucin general es:
Si se imponen estas condiciones iniciales: t=0, x=0, v=v0, la solucin queda as:
2) Solucin crtica (cuando gamma es igual a omega0)
La solucin general es:
Si se imponen estas condiciones iniciales: t=0, x=0, v=v0, la solucin queda as:
3) Solucin sobreamortiguada (cuando gamma es mayor que omega0)
La solucin general es:
Si se imponen estas condiciones iniciales: t=0, x=0, v=v0, la solucin queda as:
En este ejemplo, se van a implementar los distintos casos de un oscilador armnico amortiguado usando el patrn Estrategia (en la figura
se muestra la aplicacin del patrn para este ejemplo).
Page 19 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
package oscilador;

/**
* Esta interfaz es la estrategia abstracta del patrn Estrategia.
*
*/

public interface Fuerza {

public double calcularPosicionX(double t);

}

package oscilador;

/**
* FuerzaAmortiguadora es una estrategia concreta del patrn Estrategia.
*/

public class FuerzaAmortiguadora implements Fuerza{

/**
* Frecuencia del movimiento. (w^2 = w0^2 - gamma^2)
*/
private double omega;

/**
* Coeficiente de amortiguacin del movimiento. ( gamma = lambda/(2m) )
*/
private double gamma;

/**
* Mtodo para calcular la posicin del oscilador en el instante t.
*
* @param t double
*/
public double calcularPosicionX(double t) {
return ( (1./omega) * Math.exp(-gamma * t) * Math.sin(omega * t) );
}

/**
* Constructor.
*
* @param omega0 double
Figura 9. Aplicacin del patrn Estrategia al anlisis de los osciladores amortiguados
Page 20 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
* @param gamma double
*/
public FuerzaAmortiguadora(double omega0, double gamma) throws Exception {
if ( (omega0 > 0) && (gamma > 0) ) {
this.omega = Math.sqrt( (omega0 * omega0) - (gamma * gamma));
this.gamma = gamma;
}
else
throw new Exception("Revise las constantes del movimiento");
}

}

package oscilador;

/**
* FuerzaCritica es una estrategia concreta del patrn Estrategia.
*/

public class FuerzaCritica implements Fuerza{

/**
* Frecuencia del movimiento. (w^2 = w0^2 - gamma^2)
*/
private double omega;

/**
* Mtodo para calcular la posicin del oscilador en el instante t.
*
* @param t double
*/
public double calcularPosicionX(double t) {
return ( t * Math.exp(-omega * t) );
}

/**
* Constructor.
*
* @param omega0 double
*/
public FuerzaCritica(double omega0) throws Exception {
if ( (omega0 > 0) )
this.omega = omega0;
else
throw new Exception("Revise las constantes del movimiento");
}

}

package oscilador;


/**
* FuerzaSobreAmortiguadora es una estrategia concreta del patrn Estrategia.
*/

public class FuerzaSobreAmortiguadora implements Fuerza{

/**
* Coeficiente beta del movimiento (beta^2 = gamma^2 - w0^2)
*/
private double beta;

/**
* Coeficiente de amortiguacin del movimiento. ( gamma = lambda/(2m) )
*/
private double gamma;

/**
* Mtodo para calcular la posicin del oscilador en el instante t.
*
* @param t double
*/
public double calcularPosicionX(double t) {
return ( (1./beta) * Math.exp(-gamma * t) * ( (Math.exp(beta * t) - (Math.exp(-beta * t)) )/2. ) );
}

/**
* Constructor.
*
* @param omega0 double
* @param gamma double
*/
public FuerzaSobreAmortiguadora(double omega0, double gamma) throws Exception {
if ( (omega0 > 0) && (gamma > 0) ) {
this.beta = Math.sqrt( (gamma * gamma) - (omega0 * omega0) );
this.gamma = gamma;
}
else
throw new Exception("Revise las constantes del movimiento");
Page 21 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
}

}

package oscilador;

/**
* OsciladorAmortiguado es el contexto del patrn Estrategia.
*/

public class OsciladorAmortiguado {

/**
* Frecuencia natural del oscilador.(omega0^2) = k/m
*/
private double omega0;

/**
* Coeficiente de amortiguamiento del movimiento. gamma = lambda/(2m)
*/
private double gamma;

/**
* Velocidad inicial en el tiempo t=0.
*/
private double v0;

/**
* Tipo de fuerza.
*/
private Fuerza fuerza;

/**
* Mtodo set para fuerza.
*
* @param fuerza Fuerza
*/
public void setFuerza(Fuerza fuerza) {
this.fuerza = fuerza;
}

/**
* Mtodo para calcular la posicin del oscilador en el instante t.
*
* @param t double
*/
public double calcularPosicionX(double t) {
return(v0 * fuerza.calcularPosicionX(t));
}

/**
* Constructor
*
* @param omega0 double
* @param gamma double
* @param fuerza Fuerza
*/
public OsciladorAmortiguado(double omega0, double gamma, double v0) throws Exception {
this.omega0 = omega0;
this.gamma = gamma;
this.v0 = v0;

if (gamma < omega0)
setFuerza(new FuerzaAmortiguadora(omega0, gamma));
else if (gamma == omega0)
setFuerza (new FuerzaCritica(omega0));
else if (gamma > omega0)
setFuerza (new FuerzaSobreAmortiguadora(omega0, gamma));
else
throw new Exception("Debe elegir obligatoriamente un tipo de oscilador amortiguado");
}

// Ejemplo del funcionamiento del programa
public static void main (String args[]) throws Exception {
// Oscilador sobreamortiguado
OsciladorAmortiguado oa1 = new OsciladorAmortiguado(0.1, 0.2, 1.1);
System.out.println(oa1.calcularPosicionX(5.)); // Posicin a los cinco segundos
// Oscilador amortiguado
OsciladorAmortiguado oa2 = new OsciladorAmortiguado(0.2, 0.1, 1.1);
System.out.println(oa2.calcularPosicionX(2.)); // Posicin a los dos segundos
// Oscilador crtico
OsciladorAmortiguado oa3 = new OsciladorAmortiguado(0.2, 0.2, 1.1);
System.out.println(oa3.calcularPosicionX(3.)); // Posicin a los tres segundos


}
}

6. Ventajas y desventajas del patrn Estrategia.
Page 22 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...
El patrn Estrategia proporciona cuatro grandes ventajas:
Permite definir familias de algoritmos relacionados, lo que posibilita agrupar funciones comunes y facilitar la reutilizacin del cdigo.
Es una cmoda alternativa a la subclasificacin. Para compartir comportamientos suelen generarse subclases y redefinir los mtodos
comunes. Este patrn permite que el comportamiento cambie dinmicamente, en tiempo de ejecucin.
Elimina el uso de sentencias condicionales (if, switch/case), cuyo abuso hace difcil de leer el cdigo. En lugar de comprobar
dinmicamente que comportamiento hay que elegir, la eleccin se hace cuando se crea un objeto Estrategia.
Permite al cliente elegir entre diversas implementaciones de una misma operacin.
Pese a que [5] seala explcitamente como ventaja del patrn Estrategia la eliminacin de sentencias condicionales, creo que esa ventaja se
debe al polimorfismo, no al patrn Estrategia.
Como no poda ser de otra manera, el patrn Estrategia presenta inconvenientes. Los dos ms importantes son stos:
Incrementa el nmero de objetos que pueden ejecutarse en una aplicacin.
Puede sobrecargar innecesariamente la aplicacin si algunas implementaciones de los algoritmos no necesitan todos los argumentos
necesitados por una EstrategiaAbstracta. Un mtodo de la estrategia abstracta puede declarar muchos argumentos innecesarios para
casi todas las estrategias concretas, que habr que pasar cada vez que se escoja una estrategia concreta, sean usados o no por ella.
Por ejemplo, considrese un mtodo hacerAlgo(ArrayList al, HashMap hm, HashSet hs) de una estrategia abstracta. Por estar
declarado en la estrategia abstracta, todas las estrategias concretas debern implementarlo y debern recibir los argumentos al, hm
y hs, aun cuando slo usen uno de ellos. Como dentro de una coleccin puede haber cientos o miles de objetos, puede generarse un
trfico de datos innecesario. Una manera de paliar el paso de informacin innecesaria es aumentar el acoplamiento entre las
estrategias y el contexto, de manera que el segundo delegue en las primeras.
Los clientes deben conocer la existencia de las distintas estrategias. Si los clientes ignoran las estrategias o les resultan indiferentes,
el uso del patrn resulta inapropiado.
Recursos
[1] Working with Objects. The OORam Software Engineering Method, Trygve Reenskaug , Prentice Hall , ISBN 0134529308
[2] A Pattern Definition - Software Patterns, http://hillside.net/patterns/definition.html
[3] A Pattern Language : Towns, Buildings, Construction, Christopher Alexander, Sara Ishikawa y Murray Silverstein , Oxford
University Press , ISBN 0195019199
[4] Pattern-Oriented Software Architecture, Volume 1: A System of Patterns, Frank Buschmann, Regine Meunier, Hans
Rohnert, Peter Sommerlad, Michael Stal, Peter Sommerlad y Michael Stal , John Wiley & Sons , ISBN 0471958697
[5] Design Patterns: Elements of Reusable Object-Oriented Software, Erich Gamma, Richard Helm, Ralph Johnson y John
Vlissides , Addison-Wesley Pub Co , ISBN 0201633612
[6] Artculos sobre ingeniera del software en javaHispano, http://www.javahispano.org/articles.list.action?section=5
[7] Tutoriales sobre ingeniera del software en javaHispano, http://www.javahispano.org/tutorials.type.action?type=is
Acerca del autor
Miguel ngel Abin
Miguel ngel Abin naci en Soria. Obtuvo la suficiencia investigadora en el Dpto. de Fsica Aplicada de la Universidad de Valencia con una
tesina sobre electromagnetismo. Realiz varios cursos de doctorado relacionados con electromagnetismo, electrnica, semiconductores y
cristales fotnicos. Ha recibido becas del IMPIVA (Instituto de la Mediana y Pequea Industria Valenciana) y de la Universidad Politcnica de
Valencia. Curs un Mster estadounidense en UML y Java y otro sobre tecnologas de Internet/Intranet.
Se incorpor en 1998 a AIDIMA, donde ha participado como investigador en 24 proyectos de investigacin nacionales e internacionales
relacionados con la Web semntica, tecnologas de la informacin, madera en construccin, biosensrica, bioelectrnica,
telecomunicaciones, visin artificial; as como en la Red de Excelencia de la Comisin Europea INTEROP 2003-2007. Algunos de los
proyectos europeos relacionados con las tecnologas semnticas en los que ha participado son ATHENA y STASIS (http://www.stasis-
project.net/).
El ao 2006 estuvo cuatro meses como investigador invitado en el departamento Lehrstuhl fr Messsystem und Sensortechnik de la
Universidad Politcnica de Munich (TUM), donde colabor en el desarrollo de nuevos mtodos para la deteccin de defectos en superficies
acabadas y en el diseo e implementacin de sistemas distribuidos de sensores para el sector del automvil y de energas renovables. En
2007 recibi un premio BANCAJA-UPV por un proyecto relacionado con la calidad interna de la madera. En 2009 recibi el premio
internacional Schweighofer Innovation Prize -el premio ms prestigioso en el sector forestal y de la madera- por su aportacin al desarrollo
de nuevas tecnologas de evaluacin no destructiva de la madera en construccin.
Actualmente es Responsable del Departamento de Tecnologa y Biotecnologa de la Madera y del rea de Construccin de Madera.
Es coautor de 7 libros y guas tcnicas relacionadas con el uso de la madera en la construccin y la visin artificial. Tambin ha publicado
varios artculos cientficos en revistas como IEEE Transactions on Microwave Theory and Techniques y Wood Science and Technology. Ha
participado como ponente en congresos y conferencias como European Congress on Computational Methods in Applied Sciences and
Engineering, IEEE International Conference on Multisensor Fusion and Integration for Intelligent Systems, International Conference on
Space Structures (IABSE-IASS) y en reuniones COST (European Cooperation in Science and Technology). Ha publicado ms de 22 artculos
tcnicos en revistas sectoriales y tcnicas.
Es autor o coautor de 8 patentes, algunas de ellas en trmite. Tres de ellas corresponden a dispositivos y mtodos para detectar la
biodegradacin de la madera en construccin.
Actualmente, entre otros proyectos como SHBUILDINGS, WOODTECH, WOODRUB y CELLUWOOD, ha trabajado en SEMCONCEPT, un
proyecto de I+D+i para aplicar tecnologas semnticas (ontologas, buscadores semnticos) en el diseo conceptual de productos
industriales. Sus intereses actuales son la evolucin de la programacin orientada a objetos, Java, la Web semntica y sus tecnologas, la
arquitectura orgnica, el surrealismo y Pars, siempre Pars.
Page 23 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...

Page 24 of 24 El patrn Estrategia
21/05/2014 file://F:\ArticuloEclipse\VersinDefinitiva\Copia de patronE...

Anda mungkin juga menyukai