如何指定一个必须在抽象类中实现的枚举

本文关键字:抽象类 实现 枚举 何指定 一个 | 更新日期: 2023-09-27 18:11:22

例如,我有一个工厂类:

abstract class UnitFactory<T> where T:Unit
{
   abstract enum UnitType;
   public abstract T GetUnit(UnitType type);
}

在这里,派生类必须有一个enum(当然abstract enum不工作)来指示它可以制作哪种单元,而不是一堆字符串const,我认为这很难强制/管理。

所以我的问题是我如何使一个"抽象" enum像这样?或者如果不可能,做类似事情的最佳实践是什么?

对不起,我的英语很差,我的问题看起来很愚蠢。

编辑:示例子类:

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(...);
   }
}

如何指定一个必须在抽象类中实现的枚举

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

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

然后你需要在archer工厂外公开archer类型,否则它将无法使用。

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); 

要求每个具体工厂公开自己的类型列表意味着所有具体实现都将单独绑定到该工厂。

换句话说,绝对没有的好处:

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>
{
    ...
}