一个简单的 Generic Factory 类

简单的工厂类的一个使用场景是, 假设有一个基类 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 };

        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 的类型参数即可。

转载于:https://www.cnblogs.com/oujinliang/archive/2010/01/07/1641056.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值