Definición
El patrón estrategia define un conjunto de algoritmos, encapsula cada uno de ellos y los hace intercambiables. Estrategia permite que el algoritmo varie independientemente de los clientes que lo utilicen.
Modelo UML
Hey, Alberto stops doing that!!!
Ok chicos ya vimos todo lo que tienen que saber de memoria para impresionar a sus amigos y jefes.
Ahora vamos a tratar de aterrizar todos estos conceptos en el mundo real de forma que puedan quedar en nuestras cabezas y más importante aún que podamos utilizarlos sabiendo claramente cómo identificar el problema que resuelve este patrón de diseño.
Pensemos un poco en cada punto de la definición
El patrón estrategia define un conjunto de algoritmos…
Tenemos varios algoritmos que queremos utilizar: A, B, C etc.
…encapsula cada uno de ellos y los hace intercambiables…
OK entonces estos algoritmos (A, B, C) los podemos utilizar según necesitemos, algunas veces por ejemplo usaremos (B, C) y otras solo (A) .
…permite que el algoritmo varie independientemente de los clientes que lo utilicen.
Digamos que tenemos una lista de nombres “Smith”, “Clifford”, “Albert”, “Aurora” y los algoritmos de ordenación (A, B, C) que son totalmente independientes de la lista. Estos algoritmos de ordenación pueden ser inyectados a lista.
Un poco de UML
El Problema
Vamos al código
Observaciones
- Los perros no pueden volar pero aun asi tenemos el comportamiento volar().
- Este diseño forzaría a cada subclase como perro, cocodrilo, mono a implementar el método volar().
- Como todos sabemos no todos los animales pueden volar. Por lo tanto, no es correcto que todas las subclases tengan que implementarlo.
Usemos una interface
Una idea que nos puede venir a la cabeza para resolverlo es crear una interface volando que tenga el método volar. De esta forma solo los animales que pueden volar la implementarían.
¡Resolvimos el problema! Mmm espera… Hemos creado otro llamado “Duplicación de Código“
Esto quiere decir que si tenemos 100 animales voladores tendremos 100 implementaciones de volar().
Qué pasa si tenemos que cambiar el método volar() para varias sub-clases? Pues tendriamos que abrir cada clase que lo implemente y modificarlo.
Solución
Aca tenemos el conjuto de algoritmos del que hablaba la definicion.
Vamos a hacerlos intercambiables.
… permite que el algoritmo varie independientemente de los clientes que lo utilicen.
Ventajas de este diseño
- Otros tipos de objetos pueden reusar los diferentes comportamientos (VolarBajito, VolarAlto o NoVuelo) porque no estan ocultos en nuestras clases Animal.
- Podemos agregar nuevos comportamientos sin modificar niguno de los existentes o teniendo que tocar nuestras clases Animal.
- Podemos cambiar el comportamiento en tiempo de ejecucion dinamicamente.
El código
Animal
package com.palmer; public abstract class Animal { private String nombre; private IVolando vuelo; Animal(){} Animal(String nombre){ this.nombre = nombre; } public String getNombre() { return nombre; } public abstract void hacerSonido(); public void setVuelo(IVolando vuelo){ this.vuelo = vuelo; } public void mostrarVuelo(){ this.vuelo.volar(); } }
Pajaro
package com.palmer; public class Pajaro extends Animal { public void hacerSonido() { System.out.println("Soy un pajaro y hago sonidos de pajaro"); } }
Perro
package com.palmer; public class Perro extends Animal { public void hacerSonido() { System.out.println("Soy un pajaro y hago sonidos de perro => Guau Guau"); } }
IVolando
package com.palmer; public interface IVolando { public void volar(); }
VolandoAlto
package com.palmer; public class VolandoAlto implements IVolando { public void volar() { System.out.println("Volando Alto"); System.out.println("1: Tomar un muchaaaa energia"); System.out.println("2: Abrir mis alas"); System.out.println("3: Mantener minimo 300 pies."); } }
VolandoBajito
package com.palmer; public class VolandoBajito implements IVolando{ public void volar() { System.out.println("Volando Bajito"); System.out.println("1: Tomar un poco de energia"); System.out.println("2: Abrir mis alas"); System.out.println("3: Mantener maximo 50 pies."); } }
Main
package com.palmer; public class Main { public static void main(String[] args) { //habilidades para volar VolandoBajito vueloBajito = new VolandoBajito(); VolandoAlto vueloAlto = new VolandoAlto(); NoVuelo noVuelo = new NoVuelo(); //pajarito pequeno Animal pajaroPequeno = new Pajaro(); pajaroPequeno.setVuelo(vueloBajito); //pajaro grande Animal pajaroGrande = new Pajaro(); pajaroGrande.setVuelo(vueloAlto); //un perro x Animal perro = new Perro(); perro.setVuelo(noVuelo); //probando habilidades para volar perro.mostrarVuelo(); pajaroPequeno.mostrarVuelo(); pajaroGrande.mostrarVuelo(); } }