Posteado por: fzapataramirez | Lunes, julio 14, 2008

Patrón Strategy.

En varias ocasiones nos encontramos en situaciones donde tenemos que desarrollar una aplicación que se componen de varias clases y en las que aparentemente podemos utilizar la técnica de la herencia proporcionada por la programación orientada a objetos. Sin embargo hay que tener cuidado a la hora de utilizar la herencia entre clases ya que no siempre puede ser la mejor opción, sobre todo pensando en el tema de escalabilidad. Para entender mejor el por que, veamos el siguiente ejemplo:

Supongamos que vamos a realizar una aplicación cuyo eje central son animales (perro, tortuga y paloma). Lo primero que se nos viene a la mente es aquel ejemplo que nos dieron en la clase de programación sobre la herencia y podríamos deducir rápidamente que la mejor opción es crear una clase base “Animal”, de la cual heredarán las clases Perro, Tortuga y Paloma.

public abstract class Animal
{
    public void obtenerEstado()
    {
     }
}

Esta clase tiene un método llamado obtenerEstado, que nos servirá para saber el estado en que se encuentra el animal actualmente.

La siguiente es la clase Paloma que hereda de la clase Animal, como ha sido mencionado anteriormente.

public class Paloma : Animal
    {
        public new void obtenerEstado()
        {
            Console.WriteLine(“Volando”);
        }
    }

Como se puede observar, se utiliza la palabra clave new en la definición del método para indicar que queremos ocultar el método de la clase base (Esto también se podría hacer utilizando las palabras claves virtual y override).

El problema que se tiene con este esquema, como lo mencione anteriormente, es referente a la escalabilidad, ya que si pensamos en futuras funcionalidades (algo que es imposible dejar a un lado en el desarrollo de aplicaciones), muy posiblemente tendremos nuevas clases que hereden de la clase Paloma, las  cuales tendrán su propia implementación del método obtenerEstado. Esto se convierte en un gran problema a la hora de mantener el código, ya que cada generación de clases tendrá su propia implementación del método y en caso de que sea necesario hacer modificaciones en dicha implementación, será un trabajo tedioso.

Para evitar dicho problema surgió el patrón Strategy, el cual nos permite encapsular como objetos (Conocidos como Algoritmos en la literatura de este patrón) aquellas partes del código que probablemente tengan un cambio frecuente.

En otras palabras lo que lograremos con este patrón, es obtener una forma mas rápida y fácil de mantener el código, separando aquellas partes propensas a cambiar de esos extensos archivos de código fuente y los agrupamos en objetos separados.

Según lo anterior, la parte mas propensa al cambio en nuestro ejemplo es el método obtenerEstado, por lo tanto, se debe tratar como un objeto (Cada implementación del método se conoce como Algoritmo).

El primer paso a seguir para implementar el patrón Strategy, es definir una interface que servirá como base a todos los Algoritmos, en este caso, servirá como base a cada implementación del método obtenerEstado.

public interface AlgoritmoEstado
{
    void obtenerEstado();
}

El primer algoritmo AlgoritmoEstadoAereo, implementa la interface AlgoritmoEstado y muestra el estado del animal

image

  image

 image

Una vez se tenga la implementación completa de cada algoritmo a utilizar, se procede a incluir un atributo de tipo AlgoritmoEstado a la clase base Animal. De esta manera se podrá obtener el algoritmo que actualmente se esta utilizando en cada clase y llamar al método obtenerEstado de dicho algoritmo.

image

Ahora lo único que falta es definir que algoritmo será utilizado en cada una de nuestras clases derivadas. Esto puede realizarse en el constructor de cada una, permitiendo elegir el tipo de algoritmo en tiempo de ejecución.

image

De igual forma se implementan las clases Perro y Tortuga, estableciendo el algoritmo indicado en su constructor.

Finalmente realizamos una clase de prueba para ver que todo funcione perfectamente. Para esto creamos una instancia de cada clase (Tortuga, paloma y Perro) y llamamos el método obtenerEstado para que se muestre el estado de cada animal en consola.

image

y se obtiene el siguiente resultado …

image

Esto debido a que cada una de las clases utiliza un algoritmo diferente cuya implementación del método obtenerEstado es independiente.

Que pasaría si necesitamos que en lugar de que aparezca “Volando”, se retorne el texto: “Volando muy alto”?. En este caso, simplemente se tendría que cambiar el algoritmo AlgoritmoEstadoAereo y automáticamente se actualiza todas las clases que utilicen este algoritmo, evitándonos tener que buscar el mismo código en diferentes archivos de código muy extensos para realizar dicho cambio.

Una ventaja adicional que nos provee este patrón, es la de poder elegir el algoritmo a utilizar de manera dinámica, es decir, podemos cambiar el algoritmo a utilizar por nuestra clase según lo necesitemos.

Supongamos que la paloma en determinado momento esta corriendo en la tierra, y luego comienza a volar. Para reflejar esto en el código simplemente tendríamos que cambiar el algoritmo que utiliza la Paloma en cierto momento, como se muestra a continuación.

image

Lo cual da como resultado lo siguiente.

image 

 

Suerte !!!


Responses

  1. Leido

  2. la verdad esq me parece un muy buen ejemplo, un exelente material de estudio ya que en otras paginas que he visto no estan muy bien explicado como esta este, exelente ejemplo

  3. well.. it’s like I knew!

  4. Muy buena tu explicacion, Excelente, Gracias! Nos has ayudado mucho a poder entenderlo, justamente teniamos que investigar sobre un patrón util y habiamos seleccionado este, realmente ahorra muchos cambios y es facil de implementar, cual seria en este caso el metodo plot() que hay que redefinir si lo usamos en java? seria el obtenerEstado?

  5. Estimado Zapata Ramirez, excelente material del patron strategy, muy bien explicado y conciso.
    Espero que nos sigas apoyando con trabajos como estos..pues viniendo de ti, seguro que sera de lo mejor que hay en internet.

    Gracias.

  6. Excelente ejemplo .. gracias por la buena onda de hacer estos materiales muy utiles
    saludos

  7. muy buena forma de explicarlo, muy conciso… muchas gracias

  8. Muy bien explicado, gracias.

  9. te felicito muy simple el ejemplo, y bien explicado, y tambien muy bien lo de las imagenes se enteidne muy bien visualmente.
    Gracias.


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Categorías

A %d blogueros les gusta esto: