嵌套策略设计模式

时间:2015-02-08 15:55:25

标签: c# design-patterns unity3d

假设我们有一个控制名为Player1的角色的玩家。要在运行时启用切换武器,我有以下代码:

public interface IWeapon
{
    void Fire();
}

public class Player1Weapon1 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon1
    }
    ...
}

public class Player1Weapon2 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon2
    }
    ...
}

public class Player1
{
    IWeapon weapon;
    Player1Weapon1 w1;
    Player1Weapon2 w2;

    public Player1() 
    { 
        w1 = new  Player1Weapon1(this);
        w2 = new  Player1Weapon2(this);
        SetWeapon(w1);
    }
    void Update()
    {
        if(SWITCH_BTN_HELD)
        {
            if(weapon.equals(w1))  SetWeapon(w2);
            if(weapon.equals(w2))  SetWeapon(w1);
        }
        if(FIRE_BTN_HELD)
            weapon.Fire();
    }
    void SetWeapon(w)
    {
        weapon = w;
    }
}

完美无缺。

但现在玩家可以选择另一个名为Player2的角色。 请注意,Player2的武器与Player1不同。所以我们可以像这样添加类:

public class Player2Weapon1 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon1
    }
    ...
}
public class Player2Weapon2 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon2
    }
    ...
}

public class Player2
{
    IWeapon weapon;
    Player2Weapon1 w1;
    Player2Weapon2 w2;

    public Player2() 
    { 
        w1 = new  Player2Weapon1(this);
        w2 =new  Player2Weapon2(this);
        SetWeapon(w1);
    }
    void Update()
    {
        if(SWITCH_BTN_HELD)
        {
        if(weapon.equals(w1))  SetWeapon(w2);
        if(weapon.equals(w2))  SetWeapon(w1);
        }
        if(FIRE_BTN_HELD)
        weapon.Fire();
    }
    void SetWeapon(w)
    {
        weapon=w;
    }
}

它会再次起作用,但是非常紧张,如果玩家想玩Player3,我应该为项目添加更多类。

我想知道如何为下面的劫掠者制作战略模式:

interface IPlayer()
{

}

我不知道哪些方法会放在IPlayer中?如何创建嵌套的策略设计模式?

2 个答案:

答案 0 :(得分:4)

不确定我是否得到您要求的内容,或者您​​不知道如何/要问什么。战略模式不是你在这里最需要的。我试着给我两分钱。

首先,我认为在你的球员中加入具体的课程并不是一个好主意,比如Player1Weapon。它应该只包含IWeapon个。这样你就不需要专门定义你的玩家使用哪种武器,也不需要为每种变化创建新的玩家类。

请考虑以下事项。您在IWeapons命名空间中拥有这些SomeNamespace

public interface IWeapon
{
    void Fire();
}

public class Shotgun : IWeapon
{
    public void Fire()
    {
        Console.WriteLine("Shotgun goes boom");
    }
}

public class Knife : IWeapon
{
    public void Fire()
    {
        Console.WriteLine("Stabbed teh sucker");
    }
}

public class NuclearBomb : IWeapon
{
    public void Fire()
    {
        Console.WriteLine("Game over for everyone!!1");
    }
}

现在,您的Player课程如下所示。只需添加您可能需要的任何抽象级别,这里我假设您没有。

public class Player
{
    private IWeapon _wielded;

    public Player(string name)
        :this(name, null, null)
    {}

    public Player(string name, IWeapon primary, IWeapon secondary)
    {
        Name = name;
        Primary = _wielded = primary;
        Secondary = secondary;

        Console.WriteLine(string.Format("Player '{0}' spawned", Name));
    }

    public void Switch()
    {
        _wielded = _wielded != Primary ? Primary : Secondary;
    }

    public void Fire()
    {
        if (_wielded != null)
            _wielded.Fire();
    }

    public string Name { get; set; }

    public IWeapon Primary { get; set; }

    public IWeapon Secondary { get; set; }
}

要创建“任何玩家”,您可以拥有一个简单的工厂来“生成”它们,并将所需的属性作为参数。

public class PlayerFactory
{
    // key = player name, value = weapons
    public Player Create(KeyValuePair<string, string[]> args)
    {
        var primary = Activator.CreateInstance(Type.GetType(args.Value[0])) as IWeapon;
        var secondary = Activator.CreateInstance(Type.GetType(args.Value[1])) as IWeapon;

        var player = new Player(args.Key, primary, secondary);
        return player;
    }
}

现在如果您运行以下“初始化”...

// this would come from config file or similar
var config = new List<KeyValuePair<string, string[]>>
    {
        new KeyValuePair<string,string[]>(
            "Player1", new[] { "SomeNamespace.Shotgun", "SomeNamespace.Knife" }),
        new KeyValuePair<string,string[]>(
            "Player2", new[] { "SomeNamespace.NuclearBomb", "SomeNamespace.Knife" })
    };

var factory = new PlayerFactory();
foreach (var entry in config)
{
    var player = factory.Create(entry);
    player.Fire();
    player.Switch();
    player.Fire();
}

...您最终得到以下控制台日志

  

玩家'Player1'产生了   霰弹枪开始繁荣   刺伤了吸盘

     

玩家'Player2'产生了   每个人的游戏结束!! 1
  刺伤了傻逼

答案 1 :(得分:0)

使用Strategy模式时,您的设计可能看起来像 下面的UML图。

Player1个代表对Fire()Weapon1,...... {/ p>之一的不同武器类之一执行Weapon2操作

有关进一步的讨论,请参阅策略设计模式 在http://w3sdesign.com

public interface IWeapon
{
    void Fire();
}

public class Weapon1 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon1
    }
    ...
}

public class Weapon2 : IWeapon
{
    ...
    void Fire()
    {
        //do actions of Weapon2
    }
    ...
}

public interface IPlayer
{
    void Update();
}

public class Player1 : IPlayer
{
    private IWeapon weapon;
    private IWeapon w1;
    private IWeapon w2;

    public Player1() 
    { 
        w1 = new  Weapon1();
        w2 = new  Weapon2();
        SetWeapon(w1);
    }

    void Update()
    {
        if(SWITCH_BTN_HELD)
        {
            if(weapon.equals(w1))  SetWeapon(w2);
            if(weapon.equals(w2))  SetWeapon(w1);
        }
        if(FIRE_BTN_HELD)
            weapon.Fire();
    }
    void SetWeapon(w)
    {
        weapon = w;
    }
}