Patrones de diseño - Estrategia

El patrón Estretegia (Strategy) es un patrón de diseño de comportamiento que te permite definir una familia de algoritmos, encapsular cada uno y hacer sus objetos intercambiables. Este patrón permite que el algoritmo varíe independientemente de los clientes que lo utilicen.

Necesidad

Tenemos diferentes formas de realizar alguna tarea, por ejemplo crear una ruta de viaje de un punto a otro. La ruta va a variar dependiendo de diferentes componentes, como puede ser el medio de transporte. En lugar de crear una clase por cada medio de transporte, el patrón Estrategia sugiere que extraigas todos esos algoritmos que hacen algo específico de muchas formas diferentes para colocarlos en clases separadas llamadas estrategias. En el patrón estrategia, el comportamiento de una clase o su algoritmo se puede cambiar en tiempo de ejecución, adaptándose en este caso, a cada medio de transporte.

En este patrón intervienen los siguientes elementos:

  • Interfaz Estrategia: Es un interfaz común a todas las estrategias. Declara un método que la clase contexto utilizará para ejecutar una estrategia
  • Estrategias Concretas: Implementan distintas variaciones de un algoritmo que la clase contexto utiliza
  • Contexto: Mantiene una referencia a una de las estrategias concretas y se comunica con este objeto únicamente a través de la interfaz estrategia

Implementación

Vamos a suponer un ejemplo en el que queremos crear una aplicación para desensamblar ejecutables. Cada tipo de ejecutable tiene que ser tratado de forma diferente, en este caso solo se diferencian los ejecutables ELF y PE.

La representación de las clases sería así:

Patrón Estrategia

Código en Vala

Tenemos primero la clase abstracta  Dissasembler que actúa de interfaz de nuestra estrategia. Esta tiene una función EjeDiss() que tienen que sobrescribir las clases que lo implementen, es decir las Estrategias Concretas:

Dissasembler.vala
public abstract class Dissasembler : GLib.Object 
{  
    public abstract void EjeDiss ();  
} 

Ahora las diferentes Estrategias Concretas que heredan de la clase abstracta Dissasembler. Estos son los diferentes algoritmos, en este caso para ficheros ELF y para ficheros PE y que en este ejemplo tan solo imprimen por pantalla el tipo de ejecutable: 

ELFDissasembler.vala
public class ELFDissasembler : Dissasembler 
{ 
    public override void EjeDiss () 
    { 
        print ("Desensamblado de fichero ELF\n"); 
    } 
} 

PEDissasembler.vala
public class PEDissasembler : Dissasembler 
{ 
    public override void EjeDiss () 
    { 
        print ("Desensamblado de fichero PE\n"); 
    } 
} 

Lo siguiente es el Contexto, que en este caso llamamos DissaFile. Este mantiene una referencia a una de las estrategias concretas:

DissaFile.vala
class DissaFile : GLib.Object 
{ 
    private Dissasembler _dissasembler; 
     
    public void SetDissasembler (Dissasembler dissasembler) 
    { 
        this._dissasembler = dissasembler; 
    } 
     
    public void Desensamblar() 
    { 
        _dissasembler.EjeDiss (); 
    } 
} 

Tenemos el cliente que utiliza el patrón en la clase UsoPatronEstrategia. En este caso se instancias dos clases DissaFile y a cada una se le indica el tipo de Dissasembler (estrategia) que tiene que usar:

UsoPatronObservador.vala
class UsoPatronEstrategia : GLib.Object 
{ 
    public static int main (string[] args) 
    { 
        Intl.setlocale (ALL); 
         
        DissaFile fichero1 = new DissaFile(); 
        DissaFile fichero2 = new DissaFile(); 
         
        fichero1.SetDissasembler (new ELFDissasembler()); 
        fichero2.SetDissasembler (new PEDissasembler()); 
         
        fichero1.Desensamblar (); 
        fichero2.Desensamblar ();  
         
        return 0;  
    } 
} 

Construimos y ejecutamos el programa:

❯ valac Dissasembler.vala ELFDissasembler.vala PEDissasembler.vala DissaFile.vala UsoPatronEstrategia.vala -o UsoPatronEstrategia
❯ ./UsoPatronEstrategia
Desensamblado de fichero ELF
Desensamblado de fichero PE

Indice de Patrones

(0 votos)
Etiquetado como :

Deja un comentario

Asegúrese de introducir toda la información requerida, indicada por un asterisco (*). No se permite código HTML.