2010-08-10 36 views
16

Esto es lo que tengo hasta ahora:¿Cómo usar el patrón de estrategia con C#?

namespace Strategy 
{ 
    interface IWeaponBehavior 
    { 
     void UseWeapon(); 
    } 
} 

namespace Strategy 
{ 
    class Knife : IWeaponBehavior 
    { 
     public void UseWeapon() 
     { 
      Console.WriteLine("You used the knife to slash the enemy! SLASH SLASH!"); 
     } 
    } 
} 

namespace Strategy 
{ 
    class Pan : IWeaponBehavior 
    { 
     public void UseWeapon() 
     { 
      Console.WriteLine("You use the pan! 100% Adamantium power! BONG!"); 
     } 
    } 
} 

Ahora bien, si tengo una superclase Character.cs. ¿Cómo puede esa superclase implementar un comportamiento de arma para que las clases de niños puedan ser más específicas?

namespace Strategy 
{ 
    class Character 
    { 
     public IWeaponBehavior weapon; 

     public Character(IWeaponBehavior specificWeapon) 
     { 
      weapon = specificWeapon; 
     }   
    } 
} 

namespace Strategy 
{ 
    class Thief : Character 
    { 

    } 
} 

¿Cómo puedo aplicar esto? Estoy muy confundido sobre cuál debe ser el código real.

Sé que esto puede ser pedir demasiado, pero si usted podría escribir el código real para que pudiera estudiar, eso sería muy agradable de ustedes. Aprendo al ver el código. : P Muchas personas podrían beneficiarse de esta pregunta.

+9

El "SLASH SLASH!" reglas de parte :) – thelost

+1

Dependiendo de la otra característica de 'Character', es posible que pueda eliminar las clases heredadas y utilizar una fábrica que configure los rasgos y estrategias de Characters necesarios. –

Respuesta

26

uso de inyección de dependencia en la clase Character?

public class Character 
{ 
    public Character(IWeaponBehavior weapon) 
    { 
     this.weapon = weapon; 
    } 

    public void Attack() 
    { 
     weapon.UseWeapon(); 
    } 

    IWeaponBehavior weapon; 
} 

public class Princess: Character 
{ 
    public Princess() : base(new Pan()) { } 
} 

public class Thief: Character 
{ 
    public Thief() : base(new Knife()) { } 
} 

... 

Princess p = new Princess(); 
Thief t = new Thief(); 

p.Attack(); // pan 
t.Attack(); // knife 

Editado como solicitado.

+0

hmm me gusta el tuyo mejor que el mío, creo. –

+0

aunque hmm, la intención puede ser semánticamente más clara en la mía. –

+3

@Joshua - Pero suponiendo que todas las princesas usarán una sartén, ¿y si tienes una princesa malvada a la que le gusta usar un cuchillo ... – SwDevMan81

5

Hay algunas posibilidades. Lo que realmente estás preguntando es, "¿cómo debería saber un personaje específico qué arma usar?".

Puedes tener una fábrica de Personajes que cree e inyecte el tipo correcto de arma en el personaje (Eso sonó mal :)), o deja que el constructor de un personaje específico se encargue de crear el arma.

+1

Bien, pero sería más flexible si el arma de un personaje pudiera cambiarse en cualquier momento. Quizás el ladrón que pierde su cuchillo puede tomar una sartén e improvisar. En otras palabras, no importa cómo lo inicialices, no hay razón para hacerlo inmutable. –

+0

@Steven: supones que se necesita este nivel de flexibilidad: tampoco hay necesidad específica de hacerlo mutable. Debería hacer lo más simple que satisfaga los requisitos reales (¡cualesquiera que sean!). –

+0

@Dan: por lo que entiendo del dominio del problema, es muy probable que esta flexibilidad sea una buena idea. En definitiva, es la elección de Sergio; mi trabajo es ofrecerlo. –

3
class Character 
    { 
    private IWeaponBehavior _weapon; 

    // Constructor 
    public Character(IWeaponBehavior strategy) 
    { 
     this._weapon = strategy; 
    } 

    public void WeaponInterface() 
    { 
     _weapon.UseWeapon(); 
    } 
    } 
+2

Su constructor debe ser 'Character' not' Context'. –

+0

Gracias actualizadas. – SwDevMan81

+0

Nota al margen: si está utilizando un guion bajo para eliminar la ambigüedad de los campos de los locales, el "esto". es completamente redundante –

1
 
public class Character 
{ 
    IWeaponBehavior Weapon; 
} 

public class Princess : Character 
{ 
    Weapon = new Pan(); 
} 

public class Thief : Character 
{ 
    Weapon = new Knife(); 
} 
+5

¡debe marcar su código explícitamente como 'pseudo-código'! –

0

Si sus personajes tienen su propia arma específica, que en realidad no necesita usar el patrón de estrategia. Podría usar polimorfismo simple. Pero el patrón de estrategia podría ser más limpio de todos modos.

sólo tiene que intitialize el arma:

public class Character 
{ 
    IWeapenBehavior weapon; 

    public Attack() 
    { 
      weapon.UseWeapon(); 
    } 
} 


public class Thief : Character 
{ 
     Thief() 
     { 
      weapon = new Knife(); 
     } 
} 

En el código que controla sus caracteres, puede llamar al método Attack().

1

Tome un vistazo a la inyección de dependencias & entonces también mirar en Inversión de Control.

TekPub tiene un gran episodio libre en estas dos ideas utilizando una muestra muy similar a la suya. Esto debería ayudarte con una muestra concreta. :-)

http://tekpub.com/view/concepts/1

código de ejemplo de video:

class Samurai { 
    IWeapon _weapon; 

    public Samurai() { 
    _weapon = new Sword(); 
    } 

    public Samurai(IWeapon weapon) { 
    _weapon = weapon; 
    } 

    public void Attack(string target) { 
    _weapon.Hit(target); 
    } 
} 

Lo anterior es DI (con IWeapon constructor). Ahora, al agregar Inversion of Control, obtienes aún más control.

El uso de un contenedor COI usted será capaz de controlar el IWeapon a través de inyección en lugar de en la propia clase.

El video usa NInject ya que es IOC y muestra cómo puede eliminar el IWeapon Constructor y obtener control sobre la clase y todas las clases que necesitan usar IWeapon para usar lo que desea en un área de ubicación/configuración.

de ejemplo de video:

class WarriorModule: NinjectModule { 
    public override void Load() { 
    Bind<IWarrior>().To<Samurai>(); 
    Bind<IWeapon>().To<Sword>(); 
} 

La configuración anterior dice Ninject que cada vez que se encuentra con un iwarrior utilizar Samurai y siempre que encourters un IWeapon utilizar la espada.

El video continúa para explicar cómo este pequeño cambio aumenta su flexibilidad. Agrega otro Módulo para un Samuria que usa un arma a distancia, etc. ...

Puede cambiarlos según lo necesite/desee.

Cuestiones relacionadas