Está en la página 1de 5

STRATEGY (ESTRATEGIA)

Resumen
El patrón estrategia es útil cuando hay un conjunto de algoritmos relacionados y un objeto cliente que
necesita dinámicamente elegir uno de esos algoritmos y adaptarlos a las necesidades actuales.

Descripción
El patrón estrategia es útil cuando hay un conjunto de algoritmos relacionados y un objeto cliente que
necesita dinámicamente elegir uno de esos algoritmos y adaptarlos a las necesidades actuales.
El patrón estrategia sugiere mantener la implementación de cada algoritmo en clases separadas. Cada
algoritmo encapsulado en una clase separada es denominado una estrategia. Un objeto que usa el
objeto estrategia es denominado objeto contexto.
Con diferentes objetos estrategia, cambiar el comportamiento del objeto contexto es cuestión de
cambiar el objeto estrategia con uno de los algoritmos solicitados.
Para facilitar que el objeto contexto acceda a diferentes objetos estrategia de una manera similar, todos
los objetos estrategia deben ofrecer la misma interfaz.
Una vez que el grupo de algoritmos está encapsulado en un conjunto de clases estrategia en una
jerarquía de clases, un cliente puede escoger los algoritmos mediante la selección e instanciación de la
clase estrategia apropiada. Para cambiar el comportamiento del contexto, un objeto cliente necesita
configurar el contexto con la instancia de la estrategia seleccionada. Este tipo de arreglo separa
completamente la implementación de un algoritmo de su contexto de uso. Como resultado, cuando la
implementación de un algoritmo cambia o un nuevo algoritmo es adicionado al grupo, tanto el contexto
como el objeto cliente no se ven afectados.
Se debe tener en cuenta, que implementar diferentes algoritmos usando condicionales viola el principio
básicio open-closed. Por eso el patrón estrategia ofrece un enfoque elegante de diseño.

Ejemplo
Diseñar una clase EncryptLogger que cifre un mensaje de texto antes de enviarlo a una instancia
FileLogger (que registra el mensaje cifrado en un archivo). Para cifrar el mensaje de texto,
EncryptLogger llama al método encrypt (String).
En general, hay muchos formas diferentes de cifrar un mensaje de texto, utilizando diferentes
algoritmos de ciframiento. A continuación se explican 4 algoritmos.
• SimpleEncryption. Este algoritmo cambia el texto una posición a la derecha o a la izquierda.
Ejemplo: Texto plano: This es a message, Texto cifrado: eThis es a messag
• CaesarCypher. Este algoritmo es una rotación-sustitución donde los caracteres son cambiados
a la derecha una posición. Esto implica reemplazar la A con la B, la B con la C, …, la Z por la
A. Esto se le llama cifrado César, ya que rota el alfabeto una posición. Ejemplo: This is a
message, Texto cifrado: Uijt jt b nfttbhf. También se puede rotar 2 o n posiciones cada letra del
alfabeto.
• SubstitutionCypher. Este algoritmo utiliza una tabla de sustituciones de cada letra del alfabeto
(Ver Figura 1). Ejemplo: Texto plano: This is a Message , Texto cifrado: mWNR NR T
DXRRTnX .

1
• CodeBookCypher. Este algoritmo implica reemplazar palabras de un texto plano con su
correspondiente entrada en una tabla código-libro (code-book) (Ver Figura 2). Ejemplo: Texto
plano:This Is A True Statement , texto cifrado: Design Patterns Are Really Useful .

Los clientes de EncryptLooger deben poder seleccionar dinámicamente cualquier algoritmo de


ciframiento. Esto se puede lograr de varias maneras. Aplicando el patrón Estrategia, cada algoritmo
debe estar encapsulado en un clase separada (estrategia). Debemos diseñar una interface común
llamada EncryptionStrategy, la cual posee el método encrypt. Cada clase estrategia debe implementar
su algoritmo en el método encrypt.
EncryptLogger contiene una referencia a un objeto FileLogger. EncryptLogger utiliza diferentes
objetos Strategy y por lo tanto, actúa como contexto. Un objeto cliente que desee registrar y cifrar un
mensaje necesita crear una instancia de EncryptedLogger e invocar su método log. Cuando
EncryptLogger es instanciado por primera vez, su actual estrategia de ciframiento es establecida con
SimpleEncryption en su constructor. El cliente puede cambiar explícitamente la estrategia para cifrar,
utilizando el método setEncryptionStrategy.
La Figura 3, muestra el diseño completo.

Figura 3: Diseño

completo

2
A Código fuente en Java
A continuación el código fuente en java.
public interface EncryptionStrategy {
public String encrypt(String inputData);
}

public class CaesarCypher implements EncryptionStrategy {


public String encrypt(String inputData) {
char[] chars = inputData.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == 'z') {
c = 'a';
}
if ((c >= 'a') && (c < 'z')) {
++c;
}
chars[i] = c;
}
return new String(new String(chars));
}
}

import java.util.HashMap;
import java.util.StringTokenizer;
public class CodeBookCypher implements EncryptionStrategy {
private HashMap codeContents = new HashMap();

private void populateCodeEntries() {


codeContents.put("This","Design");
codeContents.put("is","Patterns");
codeContents.put("a","are");
codeContents.put("true","really");
codeContents.put("statement","useful");
//.........
//........
}

public String encrypt(String inputData) {


populateCodeEntries();
String outStr = "";
StringTokenizer st = new StringTokenizer(inputData);
while (st.hasMoreTokens()) {
outStr = outStr + " " + codeContents.get(st.nextToken());
}
return new String(outStr);
}
}

public class SimpleEncryption implements EncryptionStrategy {


public String encrypt(String inputData) {
inputData = inputData.substring(inputData.length() - 1)
+ inputData.substring(0, inputData.length() - 1);
return inputData;
}
}

public class SubstitutionCypher implements EncryptionStrategy {


private char[] source = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z' };
private char[] dest = { 'm', 'n', 'o', 'p', 'q', 'r', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'y', 'z', 's', 't', 'u', 'v', 'w',
'x' };

public String encrypt(String inputData) {


char[] chars = inputData.toCharArray();
for (int i = 0; i < chars.length; i++) {
3
char c = chars[i];
for (int j = 0; j < source.length; j++) {
if (source[j] == chars[i]) {
c = dest[j];
}
}
chars[i] = c;
}
return new String(chars);
}
}

public class EncryptLogger {


private EncryptionStrategy currEncryptionStrategy;
private FileLogger logger;

public EncryptLogger(FileLogger inp_logger) {


logger = inp_logger;
//set the default encryption strategy
setEncryptionStrategy(new SimpleEncryption());
}

public void log(String fileName, String msg) {


/*Added functionality*/
msg = encrypt(msg);
/*
Now forward the encrypted text to the FileLogger
for storage
*/
//logger.log(fileName, msg);
logger.logMsg(fileName, msg);

public String encrypt(String msg) {


/*
Apply encryption using the current encryption strategy
*/
return currEncryptionStrategy.encrypt(msg);
}

public void setEncryptionStrategy(EncryptionStrategy strategy) {


currEncryptionStrategy = strategy;
}
}

/**
*
* Escribe el mensaje en un archivo.
*
*/
public class FileLogger {
public void logMsg(String fileName, String msg) {
//Falta implementar el codigo que graba a un archivo, no es necesario, basta
con el mensaje.
System.out.println("Mensaje:" + msg + " grabado en el archivo" + fileName);
}
}

public class ClienteMain {


public static void main(String[] args) {
FileLogger logger = new FileLogger();
EncryptLogger eLogger = new EncryptLogger(logger);
eLogger.log("log1.txt", "this message is to be encrypted & logged");

EncryptionStrategy strategy = new SubstitutionCypher();


eLogger.setEncryptionStrategy(strategy);
eLogger.log("log2.txt", "this message is to be encrypted & logged");

strategy = new CodeBookCypher();


eLogger.setEncryptionStrategy(strategy);
4
eLogger.log("log3.txt", "This is a true statement");
}
}//End of class

Al ejecutar el cliente la salida debe ser:


Mensaje:dthis message is to be encrypted & logge grabado en el archivolog1.txt
Mensaje:zbcy gqyymaq cy zi nq qholwjzqp & fiaaqp grabado en el archivolog2.txt
Mensaje: Design Patterns are really useful grabado en el archivolog3.txt

To do
Diseñar e implementar una aplicación que permita ordenar un arreglo de datos utilizando diferentes
algoritmos de ordenamiento: burbuja, selección, shell, quick sort, etc. Aplicar el patrón estrategia.

También podría gustarte