Your approach sounds good to me. Philosophically, while your factory does know about every subclass, it doesn't know that it knows. In other words, in the future subclasses might be generated elsewhere, in places your factory knows (and cares) nothing about. At the other end, the users of these subclasses neither know nor care where they came from. Might be from the factory, might be from somewhere else.
Your bad feeling on this is that you are replacing a simple mechanism with a fancy one, and you don't (yet) really need the power you are getting. You may indeed be wasting your time. But if your system grows, you might have several factories, and many other objects might create these subclasses, including the subclasses themselves. So long as your factory does not need to know about all the subclasses, and so long as your "consumers" don't need to know which factory, if any, they came from, your design is sound. Everything is properly encapsulated and polymorphic.
One other thing: in Java more so than in other languages, a subclass often works better than putting a switch in the base class. In Java I'll subclass anything if I need a slightly different behavior. In C#, I'll go to a lot of trouble to make one class highly flexible with extra fields and extra constructor parameters. A new Java class can be created in a small block of code with no references to it elsewhere--a local or anonymous class. In C# the new class has to be placed well away from the only spot to reference it as anything but its base class--and it may be several levels of base--or interface.
switch
and if
are generally required for primitives (which $parameter
is), although PHP allows you to create class names and call methods from variables, so you can get away with a little magic.
For example you could do this:
public static function methodA($parameter = '') {
$class = '\name\space\object' . $parameter;
return new $class;
}
This of course requires that $parameter
and the existing class names are all named appropriately, and it does not account for the default case.
The other alternative requires that $parameter
be an object. You can remove the switch, but it doesn't cut down on verbosity (although it is polymorphic). One possible way:
public static function methodA(EncodingType $parameter = null) {
return new $parameter->getObject();
}
...which would return the required object string.
I should note that the principle of avoiding conditionals in contemplation of using polymorphism is great, especially in theory -- but if you try to eliminate all conditionals in your code you can half kill yourself and end up writing unnecessarily complicated code. It may also be a signal to rethink your design.
I will say that one common spot where you find conditionals is in factory methods, which is what your example seems to be.
Best Answer
I guess it depends on how it is used.
Essentially the Factory pattern is a reference to a set of objects. Normally combined with something else, possibly like the Strategy pattern (which is more likely to be defined as a type of polymorphism) to provide reference to an object to act on.
The Abstract Factory Pattern by itself is intended to be polymorphic as it is defined as an abstract class type. However the concrete implementation of the factory is the
WidgetFactory
in your type and is only polymorphic in reference to using a factory and providing an implementation of a factory.In terms of what you are after, you certainly require a concrete factory, and presumably the actions you perform depend on the exception being caught. To that end you would use your factory implementation in a non-polymorphic way simply by passing it the exception caught, and have the factory pattern return a method to invoke a strategy or even a chain-of-command pattern to deal with how you would like to handle the exception.
Therefore, your factory would not necessarily be polymorphic, and your exception handlers would be polymorphic.