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();
}
}
我的问题是:
- 哪个实现更快,
- 哪个更readable/easier理解,
- 你会使用哪个,为什么?
使用反射更易于维护。
永远不要使用switch
,因为当你添加新的class时,你也必须修改这个switch语句。
第二种方法不可接受。 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]();
}
}
它比第一个变体更简洁。性能几乎相同。
给定 类:
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();
}
}
我的问题是:
- 哪个实现更快,
- 哪个更readable/easier理解,
- 你会使用哪个,为什么?
使用反射更易于维护。
永远不要使用
switch
,因为当你添加新的class时,你也必须修改这个switch语句。第二种方法不可接受。 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]();
}
}
它比第一个变体更简洁。性能几乎相同。