Saltar al contenido

¿Cuándo y por qué se debe utilizar el Patrón de estrategia?

Después de consultar especialistas en la materia, programadores de diversas áreas y maestros hemos dado con la solución a la cuestión y la dejamos plasmada en este post.

Solución:

El problema con ejemplos de juguetes como este es que a menudo es fácil perder el punto. En este caso, el código podría implementarse simplemente como lo ha mostrado. En un patrón de estrategia, el valor principal está en poder cambiar diferentes implementaciones para diferentes situaciones.

El ejemplo que tiene solo ilustra los objetos en el patrón y las interacciones entre ellos. En cambio, imagine que tiene un componente que genera gráficos para un sitio web dependiendo de si es una computadora de escritorio o un teléfono inteligente en el otro extremo, tendría algún código que detectaría el tipo de navegador que crearía y establecería la estrategia en otro componente que podría use el objeto de estrategia en algún código complejo que no necesitaría ser duplicado y haría el trabajo en ambas situaciones dejando los detalles del dibujo real del gráfico al objeto de estrategia apropiado:

interface GraphStrategy 
    Image renderGraph(Data graphData);


class BigGraphStrategy implements GraphStrategy 
    ...


class SmallGraphStrategy implements GraphStrategy 
    ...

Luego en algún otro código:

GraphStrategy graphStrategy;

if (phoneBrowser == true)  
    graphStrategy = new SmallGraphStrategy();
 else 
    graphStrategy = new BigGraphStrategy();

El resto del código de su aplicación puede simplemente usar graphStrategy.renderGraph() sin tener que saber si se está realizando una renderización de imagen completa o pequeña.

Áreas que vienen a la mente:

  • Un asignador de recursos. En la gestión manual de recursos, esto podría ser minimizar el tiempo que tarda el recurso en asignarse o minimizar la fragmentación. Cada estrategia aquí tiene un método “Asignar” que tiene la misma interfaz, y el usuario toma una decisión sobre qué estrategia usar en función de lo que está tratando de optimizar.
  • Un método para conectar y enviar datos de red. Tal vez en algunos casos preferiría conectarse y enviar datagramas UDP, tal vez en otras situaciones donde el rendimiento era un factor menor que enviaría usando TCP/IP.
  • Estrategia de formateo/serialización de datos. Permita que el código decida si un objeto debe serializarse con Json o con Xml. Tal vez uno para máquinas y el otro para situaciones legibles por humanos. Ambas estrategias tienen un método de “Serialización” que toma un objeto. Cada uno serializa de manera diferente.

El tema es que la decisión de hacer algo de una manera u otra depende de factores situacionales, y usted o su código elegirían la estrategia correcta en función de la situación.

Ahora, ¿por qué sería esto más útil que algo como:

void DoIt()

    if (... situation1...)
    
       DoA()
    
    else
    
       DoB();
    

La razón es que a veces quieres tomar la decisión una vez y olvidarte de ella. El otro tema importante del patrón de estrategia es que se desacopla la decisión sobre qué estrategia usar del código que necesita para ejecutar la estrategia.

DoItStrategy MakeDoItStrategy()

     if (... situation1...)
     
           return new DoItStrategyA();
     
     else
     
           return new DoItStrategyB();
     

En el último ejemplo, puede simplemente almacenar la estrategia, pasándola como un objeto más que implementa la interfaz de estrategia. Para aquellos que ejecutan la estrategia, simplemente tienen una forma de realizar una acción. No saben cuál es el funcionamiento interno debajo del capó, solo que la interfaz estará satisfecha. Los usuarios de la estrategia no deberían necesitar saber por qué tomamos una decisión. Solo necesitan hacer una acción. Tomamos una decisión una vez y pasamos la estrategia a las clases que usan la estrategia.

Por ejemplo, considere el caso en el que tomamos una decisión de todo el programa, en función de una configuración de red dada, para conectar y enviar datos a hosts remotos con UDP. En lugar de que cada usuario de la interfaz de red necesite conocer la lógica para tomar la decisión (la función “Hazlo” anterior), podemos crear la estrategia UDP por adelantado y pasarla a todos los que necesitan enviar datos de red. Esta estrategia luego implementa una interfaz simple con el mismo resultado final: los datos van de A a B.

El fragmento de código que está citando es un poco engañoso porque está (ligeramente) fuera de contexto. Lo que está escribiendo a continuación en su ejemplo también es el patrón de estrategia: acaba de volver a escribir el ejemplo anterior de manera un poco más concisa.

El punto principal en el ejemplo es que los detalles de la operación matemática se abstraen de la persona que llama. De esta manera, la persona que llama puede trabajar con cualquier operador binario creando una nueva ConcreteStrategy, por ejemplo

  int mod = new ConcreteStrategy() 
         public int execute(int a, int b) return a %b; 
  .execute(3,4);

Comentarios y puntuaciones del tutorial

Puedes añadir valor a nuestra información cooperando tu veteranía en las interpretaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *