2016-10-04 36 views
1

例如,我有一個工廠類:C# - 如何指定一個枚舉必須在抽象類中實現?

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

    public abstract T GetUnit(UnitType type); 
} 

這裏,派生類必須有一個枚舉(當然abstract 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(...); 
    } 
} 
+0

d oes'abstract enum'是什麼意思?枚舉不支持繼承。他們只是值 –

+0

枚舉是一種值類型,可悲的是,你不能從它得到任何東西 –

+2

這聽起來像[XY問題]的案例(http://meta.stackexchange.com/questions/66377/what-是最XY-問題)。假設Y是解決方案(抽象枚舉),當它不起作用時,請求Y,而不是實際問題X. X的問題是什麼? –

回答

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

輝煌!我真的沒有考慮將enum作爲類型參數傳遞。但是,我可以限制第一個類型參數是枚舉嗎? – Tr1et

+0

雖然你應該只用一個UnitType枚舉,並將不同的構造函數委託註冊到具有不同枚舉值的1個工廠......所以可以使用UnitFactory.Create(UnitType.LongBowman)。不需要克隆等。 –

+0

在工廠內新增註冊功能的例子,使您的生活更輕鬆,無需擔心克隆。 –

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> 
{ 
    ... 
} 
相關問題