C#:开关与工厂中的方法重载 class

C#: switch vs method overload in factory class

给定 类:

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. 哪个更readable/easier理解,
  3. 你会使用哪个,为什么?

使用反射更易于维护。

  1. 永远不要使用switch,因为当你添加新的class时,你也必须修改这个switch语句。

  2. 第二种方法不可接受。 a、b、c来自哪里?你必须 new 他们没有工厂方法。

同时检查一些 IoC containers

我真的建议您将其作为 IoC 容器。 无论如何,也许你只是有一些 classes 想要确保在 .ctor 之后 class 发生某些事情,这种方法将起作用并且你不必使用开关.

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));
}

你可以这样使用:

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]();
    }
}

它比第一个变体更简洁。性能几乎相同。