一个简单的Generic Factory类2011-01-09 博客园 Ahha简单的工厂类的一个使用场景是,假设有一个基类 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 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(FactoryKeyAttribute)) where key != null && typeof(TBaseClass).IsAssignableFrom(type) select new { Key = key, Value = type };
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 的类型参数即可。