C#:工厂类

时间:2015-11-05 12:50:16

标签: c# performance switch-statement overloading

鉴于课程:

enum ThingEnum { A,B,C}

interface IThing { }

class A : IThing { }

class B : IThing { }

class C: IThing { }

我脑子里有两个IThingFactory的实现。一个使用switch

class ThingFactory
{
    public IThing MakeThing(ThingEnum type)
    {
        switch (type)
        {
            case ThingEnum.A:
                return new A();
                break;
            case ThingEnum.B:
                return new B();
                break;
            case ThingEnum.C:
                return new C();
                break;
            default:
                break;
        }
    }
}

另一个使用抽象和方法重载:

class ThingFactory
{
    public IThing Make(A a)
    {
        return new A();
    }

    public IThing Make(B a)
    {
        return new B();
    }

    public IThing Make(C a)
    {
        return new C();
    }
}

我的问题是:

  1. 哪种实施更快,
  2. 更易读/更容易理解,
  3. 您将使用哪些以及为什么?

3 个答案:

答案 0 :(得分:6)

我真的建议您使用IoC容器作为您的方法。 无论如何,也许你只是有一些你想要做的课程,确保在.ctor之后课堂上发生了一些事情,这种方法可行,你不必使用开关。

class IThingFactory
{
    public IThing MakeThing<T>() where T : IThing, new()
    {
         var thing = new T();
         thing.Init(); // has to be part of the IThing interface.
         return thing;
    }
}

这是一种更通用的方法

class IThingFactory
{
    private IDictionary<Type, Func<IThing>> factories = new Dictionary<Type, Func<IThing>>();

    public void Register(Type t, Func<IThing> factory);
    {
         if(!typeof(IThing).IsAssignableFrom(t))
             throw new ArgumentException("This is not a thing");
         this.factories.Add(t, factory);
    }

    public void Register<T>() where T : IThing, new()
    {
        this.Register<T>(() => new T());
    }

    public void Register<T>(Func<IThing> factory) where T : IThing
    {
        this.Register(typeof(T), factory);
    }

    public IThing MakeThing(Type type);
    {
        if (!factories.ContainsKey(type))
             throw new ArgumentException("I don't know this thing");
        return factories[type]();
    }
}

public void Main()
{
     var factory = new IThingFactory();
     factory.Register(typeof(A), () => new A());
     factory.Register<B>();
     factory.Register<C>(() => new C("Test"));
     var instance = factory.MakeThing(typeof(A));
}

答案 1 :(得分:2)

使用反射更易于维护。

  1. 永远不要使用switch,因为在添加新类时,您还必须修改此switch语句。

  2. 第二种方法是不可接受的。 a,b,c在哪里?你必须new没有工厂方法。

  3. 同时检查一些IoC containers

答案 2 :(得分:1)

您可以使用以下内容:

internal static class Factory
{
    internal static Dictionary<ThingEnum, Func<IThing>> ctors = new Dictionary<ThingEnum, Func<IThing>>
    {
        {ThingEnum.A, () => new A() },
        {ThingEnum.B, () => new B() },
        {ThingEnum.C, () => new C() }
    };

    internal static IThing MakeThing(ThingEnum type)
    {
        return ctors[type]();
    }
}

它比第一个变体更简洁。表现几乎相同。