I'm refactoring a legacy codebase.
I have 4 very similar objects that I decided would be a good target for becoming polymorphic, so I moved all the common code to a base class and added an interface.
The real problem arises when trying to create those objects. Every class has 3 different constructors with 5-10 parameters each, used in different cases based on the context.
I already know those classes have too much going on, and would actually be better split in different, smaller classes, each one dealing with one case, however this is a legacy codebase and I can't do so many changes to the existing code.
At the moment my code is something like this:
public class HandlerFactory
{
public static IHandler CreateInstance(HandlerType param1, string param2, ..., string param8)
{
switch(param1)
{
case HandlerType.Type1
return new Handler1(param2, ..., param8)
case HandlerType.Type2
return new Handler2(param2, ..., param8)
case HandlerType.Type3
return new Handler3(param2, ..., param8)
case HandlerType.Type4
return new Handler4(param2, ..., param8)
}
}
public static IHandler CreateInstance(HandlerType param1, int param2, ..., DateTime param10)
{
switch(param1)
{
case HandlerType.Type1
return new Handler1(param2, ..., param10)
case HandlerType.Type2
return new Handler2(param2, ..., param10)
case HandlerType.Type3
return new Handler3(param2, ..., param10)
case HandlerType.Type4
return new Handler4(param2, ..., param10)
}
}
public static IHandler CreateInstance(HandlerType param1, string param2, ..., CustomClass param5)
{
switch(param1)
{
case HandlerType.Type1
return new Handler1(param2, ..., param5)
case HandlerType.Type2
return new Handler2(param2, ..., param5)
case HandlerType.Type3
return new Handler3(param2, ..., param5)
case HandlerType.Type4
return new Handler4(param2, ..., param5)
}
}
}
However, I hate having 3 factory methods, as I now have to edit three of them if I were to add another Handler (the main reason I'm doing this refactoring).
Is there a way I can keep just one factory method with a single switch?
Best Answer
The answer provided by @JohnWu is very elegant and I like it a lot. Allow me to provide an alternative.
You could use Abstract Factory Pattern. You would basically have one big factory of factories, which would then produce the concrete factories for concrete handlers. Then, should you need another handler, all you would need to do is write one factory for that particular handler. It would be something along these lines:
For simplicity, I have only two Handler classes with two different constructors. I believe the solution still can be applied to your case. Next, we have factories:
The alternative here would be to have a
HandlerFactory
class that would have a property ofIHandlerFactory
type, and the methods would not be static and would not haveIHandlerFactory
parameter in them. Obviously, an object ofHandlerFactory
class would need to be instantiated at some point.The usage would go somehow like this:
The solution clearly divides the code by purpose, and most importantly, should you have the need for another handler, you would not need to change the existing code. All you would have to do is write a factory for that particular handler.
Remember, this is only possible because all handlers have the constructors with same parameter lists. The design would be somewhat different if that was not the case.