Reputation: 1527
Given classes:
enum ThingEnum { A,B,C}
interface IThing { }
class A : IThing { }
class B : IThing { }
class C: IThing { }
I have two implementations of IThingFactory
in my head. One using 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;
}
}
}
Another using abstraction and method overload:
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();
}
}
My questions are:
Upvotes: 2
Views: 1019
Reputation: 31723
I would really suggest as IoC container for your approach.
Anyway, maybe you just have some classes where you want to do ensure something happens to the class after the .ctor
, this approach will work and you don't have to use a switch.
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;
}
}
a more generic approach would be this
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));
}
Upvotes: 6
Reputation: 674
You can use something like this:
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]();
}
}
it's more laconic then first variant. Performance will be almost the same.
Upvotes: 1
Reputation: 7036
Using reflection is more maintainable.
Never use switch
because when you add new class, you have to modify this switch statement as well.
Second approach is not acceptable. Where are a, b, c from? You have to new
them without factory method.
Also check some IoC containers.
Upvotes: 2