Imaginemos un videojuego de aventuras. En el video juego aparecerán personajes jugadores y personajes no jugadores con diferentes características.
En nuestro mundo mágico imaginado habrá criaturas tales como magos, guerreros, trolls, etc…
Algunos de estos personajes podrán usar armas y otros no, algunos podrán usar magia y otros no, y algunos podrán volar y otros no. La combinación de estas habilidades dependerá de las clases que implementen las habilidades de estas criaturas fantásticas.
Para conseguir estos comportamientos podemos usar el patrón de diseño Estrategia.
El patrón Estrategia define una familia de algoritmos, encapsula cada uno y los hace intercambiables. Estrategia permite al algoritmo ser modificado independientemente de los clientes que los usan.
Para nuestro mundo mágico, estas familias de algoritmos serían familias de habilidades (volar, usar magia, usar un arma)
En primer lugar creamos un interfaz común para cada habilidad, y cada implementación lleva su propio algoritmo que determina la forma de realizar esa habilidad.
public interface IHabilidadArma
{
void UsarArma();
}
public class HabilidadArmaArco : IHabilidadArma
{
public void UsarArma()
{
Console.WriteLine("Realiza un ataque con un arco lanzando una flecha");
}
}
public class HabilidadArmaEspada : IHabilidadArma
{
public void UsarArma()
{
Console.WriteLine("Realiza un ataque con la espada");
}
}
Y así todas las habilidades e implementaciones que necesitemos.
Crearemos una clase abstracta llamada PersonajeAbstracto, en el que estarán todas las acciones comunes a todas las criaturas; por ejemplo: puntos de vida, desplazarse, display en el caso de que haya gráficos, etc. Y también habrá unos métodos para inicializar las habilidades y otros para hacer uso de ellas; como setHabilidadArma(IHabilidadArma implementacion) o UsarHabilidadArma().
public abstract class PersonajeAbstracto
{
#region POSIBLES HABILIDADES DE LA CRIATURA
private IHabilidadArma HabilidadDeArmas;
private IHabilidadMagia HabilidadMagica;
private IHabilidadVolar HabilidadDeVolar;
#endregion
#region ELEMENTOS COMUNES A TODOS
public abstract string DisplayName { get; }
public int PuntosDeVida { get; set; }
public void Desplazarse() { /* Implementa desplazamiento */}
#endregion
#region INICIALIZADORES DE COMPORTAMIENTOS
// Con estos métodos podemos cambiar los comportamientos en tiempo de
ejecución
public void setHabilidadArma(IHabilidadArma habArma)
{
this.HabilidadDeArmas = habArma;
}
public void setHabilidadMagia(IHabilidadMagia habMagia)
{
this.HabilidadMagica = habMagia;
}
public void setHabilidadVolar(IHabilidadVolar habVolar)
{
this.HabilidadDeVolar = habVolar;
}
#endregion
#region EJECUTAR HABILIDADES
public void UsarHabilidadArma()
{
this.HabilidadDeArmas.UsarArma();
}
public void UsarHabilidadMagia()
{
this.HabilidadMagica.UsarMagia();
}
public void UsarHabilidadVolar()
{
this.HabilidadDeVolar.Volar();
}
#endregion
}
Cada implementación de esta clase abstracta en su constructor inicializa las habilidades correspondientes a cada criatura.
public class Elfo : PersonajeAbstracto
{
// constructor
public Elfo()
{
// un elfo usa su arco
this.setHabilidadArma(new HabilidadArmaArco());
// un elfo no sabe usar magia
this.setHabilidadMagia(new NoHabilidadMagia());
// un elfo vuela :P
this.setHabilidadVolar(new HabilidadVolar());
}
public override string DisplayName { get { return "Elfo"; }
}
}
En este caso hemos creado un elfo que dispara flechas con su arco, no tiene capacidad de usar magia y aparte de esto, nuestro elfo vuela, entre otras cosas por que a mí me da la gana. :P
Como los métodos que asignan las habilidades son públicos, podríamos hacer que cambiaran estas habilidades en tiempo de ejecución. Por ejemplo si queremos que nuestro elfo no vuele, podemos usar el código marcado en amarillo:
// ELFO
PersonajeAbstracto elfo = new Elfo();
Console.WriteLine(elfo.DisplayName);
// usa tu habilidad para disparar con arco
elfo.UsarHabilidadArma();
// intenta usar magia
elfo.UsarHabilidadMagia();
// los elfos vuelan ¿?
elfo.UsarHabilidadVolar();
// un poderoso mago hechiza a nuestro elfo y le deshabilita la capacidad de volar!!!
elfo.setHabilidadVolar(new NoHabilidadVolar());
// Noooooooooo!!! ya no puedes volar!!!
elfo.UsarHabilidadVolar();
Podemos ver un diagrama genérico de nuestras criaturas:

El código fuente lo podéis descargar en el siguiente enlace:
http://blogs.renacimiento.com/cmerino/Source/PatronEstrategia.rar