一個簡單的 Generic Factory 類

作者: Ahha  來源: 博客園  發布時間: 2010-01-07 11:38  閱讀: 2042 次  推薦: 0   原文鏈接   [收藏]  

  簡單的工廠類的一個使用場景是, 假設有一個基類 BaseClass, 和一系列的子類 A, B, C, 工廠類根據某個參數,例如字符串 “A”, “B”, “C” 創建出相應的子類。 舉例如下:

public class Factory
{
    public static BaseClass Create(string name)
    {
        switch (name)
        {
            case "A": return new A();
            case "B": return new B();
            case "C": return new C();
            default: throw new ArgumentException("Wrong Name");
        }
    }
}

  這里的一個問題是, 當子類增加或減少時, Factory 類 需要相應的改動。 有沒有辦法可以只是改動子類本身, 而不用修改Factory類呢, 當然有,這里我舉一個簡單的實現。

  基本思想是在每個子類上附加一個 Attribute, 定義如下:

[AttributeUsage(AttributeTargets.Class)]
public class FactoryKeyAttribute : Attribute
{
    public object Key { get; set; }
}

  假設我們有基類和子類實現如下

public abstract class BaseClass {}

[FactoryKey(Key = "Standard")]
public class Standard : BaseClass {}

[FactoryKey(Key = "Enterprise")]
public class Enterprise : BaseClass {}

[FactoryKey(Key = "Lite")]
public class Lite : BaseClass {}

 

  假設這些類都在同一個 Assembly中 (對于不在同一個Assembly的,實現會稍微復雜些)工廠類需要預先加載 Key => Type 的Mapping, 然后根據Key創建不同的實例, 實現如下:

public static class Factory<TKey, TBaseClass>
{
    private static readonly IDictionary<TKey, Type> TypeDict = Init();
    private static IDictionary<TKey, Type> Init()
    {
        var dict = from type in Assembly.GetExecutingAssembly().GetTypes()
                   let key = (FactoryKeyAttribute)Attribute.GetCustomAttribute(type, typeof(FactoryK
eyAttribute))
                   where key != null && type.IsSubclassOf(typeof(TBaseClass))
                   select new { Key = key, Value = type };

        return dict.ToDictionary(kvp => (TKey)kvp.Key.Key, kvp => kvp.Value);
    }

    public static TBaseClass CreateInstance(TKey key)
    {
        Type type;
        if (TypeDict.TryGetValue(key, out type))
        {
            return (TBaseClass)Activator.CreateInstance(type);
        }

        throw new ArgumentException("Incorrect Key!");
    }
}

  使用方法也很簡單:

BaseClass s = Factory<string, BaseClass>.CreateInstance("Standard");
BaseClass l = Factory<string, BaseClass>.CreateInstance("Lite");
BaseClass e = Factory<string, BaseClass>.CreateInstance("Enterprise");

 

  對于其他類型的Key,比如 Enum, 或其他類型的基類, 改變Factory 的類型參數即可。

0
2
 
標簽:Generic
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()