C# - 如何指定枚举必须在抽象类中实现?

时间:2016-10-04 12:09:07

标签: c# enums factory

例如,我有一个工厂类:

abstract class UnitFactory<T> where T:Unit
{
   abstract enum UnitType;

   public abstract T GetUnit(UnitType type);
}

这里,派生类必须有一个枚举(当然abstract enum不起作用)来表示它可以制作哪种单位,而不是一串字符串我认为很难执行/管理。

所以我的问题是如何制作像这样的“abstract”枚举?或者,如果不可能,做类似事情的最佳做法是什么?

抱歉我的英语不好以及我看似愚蠢的问题。

编辑: 示例子类:

class ArcherFactory : UnitFactory<Archer>
{
   private static Archer _baseLongbowman = ....;
   private static Archer _baseCrossbowman = ....;

   // Child class must have a implementation of UnitType enum to
   // tell the user that it can only make those kind of units.
   public enum UnitType{ Longbowman, Crossbowman }

   public override Archer getUnit(UnitType type)
   {
      if (type == UnitType.Longbowman) return _baseLongbowman.Clone(...);
      return _baseCrossbowman.Clone(...);
   }
}

2 个答案:

答案 0 :(得分:2)

您应该为抽象工厂定义两种泛型类型

public abstract class UnitFactory<TType, TUnit> where TUnit:Unit
{
    public abstract TUnit GetUnit(TType type);
}

然后你需要在射手工厂外面展示射手类型,否则它将无法使用。

public enum ArcherType { Longbowman, Crossbowman }

最终创建了射手工厂。

public class ArcherFactory : UnitFactory<ArcherType, Archer>
{
    private static Archer _baseLongbowman = ....;
    private static Archer _baseCrossbowman = ....;

    public override Archer GetUnit(ArcherType type)
    {
        switch (type)
        {
            case ArcherType.Crossbowman:
                return  _baseCrossbowman.Clone(...);

            default:
                return  _baseLongbowman.Clone(...);

        }
    }
}

编辑:

使用静态实例和克隆,您可以使用Func创建每个单元的单独实例。

public class ArcherFactory : UnitFactory<ArcherType, Archer>
{
    public ArcherFactory()
    {
        this.Register(ArcherType.Longbowman, () => new Archer(...));
        this.Register(ArcherType.Crossbowman, () => new Archer(...));
    }
}

public abstract class UnitFactory<TType, TUnit>
{
    private readonly Dictionary<TType, Func<TUnit>> factoryMethods = new Dictionary<TType, Func<TUnit>>();

    protected void Register(TType type, Func<TUnit> constructorFuc)
    {
        // perform some sanity checks
        this.factoryMethods.Add(type, constructorFuc);
    }

    public TUnit GetUnit(TType type)
    {
        // perform some sanity checks
        return this.factoryMethods[type]();
    }
}

并使用

var archerFactory = new ArcherFactory();
var crossbowMan = archerFactory.GetUnit(ArcherType.Crossbowman); 

答案 1 :(得分:0)

要求每个具体工厂公开自己的类型列表意味着所有具体实施都将仅与该工厂相关联。

换句话说,完成没有好处

var longbowman = archerFactory.GetUnit(ArcherFactory.UnitType.Longbowman);
var crossbowman = archerFactory.GetUnit(ArcherFactory.UnitType.Crossbowman);

与简单相比:

// this is better than a huge switch/case method
var longbowman = archerFactory.GetLongbowman()
var crossbowman  = archerFactory.GetCrossbowman();

要使抽象工厂模式有意义,您需要在工厂中单独定义类型,即

enum ArcherType { Longbowman, Crossbowman }

interface IFactory<Ttype, Tvalue>
{
    Tvalue GetUnit(Ttype);
}

interface IArcherFactory : IFactory<ArcherType, Archer>
{
    ...
}