Factory pattern (or at least the use of FactoryFactory..
) is the butt of many jokes, like here.
Apart from having verbose and “creative” names like RequestProcessorFactoryFactory.RequestProcessorFactory, is there anything fundamentally wrong with the factory pattern if you have to program in Java/C++ and there is a usecase for Abstract_factory_pattern?
How would another popular language (for example, Ruby or Scala) avoid having to use it while managing similar complexity?
The reason I am asking is I see mostly the criticism of factories mentioned in the context of the Java/Java EE ecosystem, but they never explain how other languages/frameworks solve them.
3
Your question is tagged with “Java”, no surprise you’re asking why is the Factory pattern being mocked: Java itself comes with a nicely packaged abuses of that pattern.
For example try loading an XML document from a file and run an XPath query against it. You need something like 10 lines of code just to setup the Factories and Builders:
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(new FileInputStream("c:\employees.xml"));
XPath xPath = XPathFactory.newInstance().newXPath();
xPath.compile(expression).evaluate(xmlDocument);
I wonder if the guys designing this API ever worked as developers or did they just read books and throw things around. I understand they just didn’t want to write a parser themselves and left the task to others but it still makes for an ugly implementation.
Since you’re asking what’s the alternative here’s loading the XML file in C#:
XDocument xml = XDocument.Load("c:\employees.xml");
var nodes = xml.XPathSelectElements(expression);
I suspect newly hatched Java developers see the Factory madness and think it’s OK to do that – if the geniuses who built Java themselves have used them that much.
Factory and any Other patterns are tools, each suited for a particular job. If you apply them to jobs they aren’t suited for you’re bound to have ugly code.
1
As so often, people misunderstand what’s going on (and that includes many of the laughers).
It’s not the factory pattern per se that’s bad as much as the way many (maybe even most) people use it.
And that no doubt stems from the way programming (and patterns) is taught. Schoolkids (often calling themselves “students”) get told to “create X using pattern Y” and after a few iterations of that think that that’s the way to approach any programming problem.
So they start applying a specific pattern they happen to like in school against anything and everything, whether it’s appropriate or not.
And that includes university professors who write books about software design, sadly.
The culmination of this was a system I had the distinct displeasure of having to maintain which had been created by one such (the man even had several books about object oriented design to his name, and a teaching position in the CS department of a major university).
It was based on a 3 tier pattern, with each tier itself a 3 tier system (have to decouple…). On the interface between each set of tiers, on both sides, was a factory to produce the objects to transfer data to the other tier, and a factory to produce the object to translate the received object to one belonging to the receiving layer.
For each factory there was an abstract factory (who knows, the factory might have to change and then you don’t want the calling code to have to change…).
And that whole mess was of course completely undocumented.
The system had a database normalised to 5th normal form (I kid you not).
A system that was essentially little more than an address book that could be used to log and track incoming and outgoing documents, it had a 100MB codebase in C++ and over 50 database tables. Printing 500 form letters would take as long as 72 hours using a printer connected directly to the computer running the software.
THAT’s why people scoff patterns, and specifically people focusing singlemindedly on a single specific pattern.
10
Factories have many advantages which allow for elegant application designs in some situations. One is that you can set the properties of objects you later want to create in one place by creating a factory, and then hand that factory around. But often you don’t actually need to do that. In that case using a Factory just adds additional complexity without actually giving you anything in return. Let’s take this factory, for example:
WidgetFactory redWidgetFactory = new ColoredWidgetFactory(COLOR_RED);
Widget widget = redWidgetFactory.create();
One alternative to the Factory pattern is the very similar Builder pattern. The main difference is that the properties of the objects created by a Factory are set when the Factory is initialized, while a Builder is initialized with a default state and all properties are set afterwards.
WidgetBuilder widgetBuilder = new WidgetBuilder();
widgetBuilder.setColor(COLOR_RED);
Widget widget = widgetBuilder.create();
But when overengineering is your problem, replacing a Factory with a Builder is likely not much of an improvement.
The most simple replacement for either pattern is of course to create object-instances with a simple constructor with the new
operator:
Widget widget = new ColoredWidget(COLOR_RED);
Constructors, however, have a crucial drawback in most object-oriented languages: They must return an object of that exact class and can not return a sub-type.
When you need to choose the sub-type at runtime but don’t want to resort to creating a whole new Builder or Factory class for that, you can use a factory-method instead. This is a static method of a class which returns a new instances of that class or one of its sub-classes. A Factory which does not maintain any internal state can often be replaced with such a factory-method:
Widget widget = Widget.createColoredWidget(COLOR_RED); // returns an object of class RedColoredWidget
A new feature in Java 8 are method references which allow you to pass methods around, just like you would do with a stateless factory. Conveniently, anything which accepts a method reference also accepts any object which implements the same functional interface, which can also be a full-fledged Factory with internal state, so you can easily introduce factories later, when you see a reason for doing so.
5
Factories of one sort or another are found in pretty much any object-oriented language under appropriate circumstances. Sometimes you just plain need a way to select what kind of object to create based on a simple parameter like a string.
Some people take it too far and try to architect their code to never need to call a constructor except inside a factory. Things start to get ridiculous when you have factory factories.
What struck me when I learned Scala, and I don’t know Ruby, but believe it is much the same way, is that the language is expressive enough that programmers aren’t always trying to push the “plumbing” work to external configuration files. Rather than being tempted to create factory factories to wire your classes together in different configurations, in Scala you use objects with traits mixed in. It’s also relatively easy to create simple DSLs in-language for tasks that are often way over-engineered in Java.
Also, as other comments and answers have pointed out, closures and first class functions obviate the need for many patterns. For that reason, I believe many of the anti-patterns will start disappearing as C++11 and Java 8 gain widespread adoption.
2
In general, there is this trend that Java programs are horrendously over-engineered [citation needed]. Having many factories is one of the most common symptoms of over-engineering; that’s why people make fun of those.
In particular, the problem Java has with factories is that in Java a) constructors are not functions and b) functions are not first-class citizens.
Imagine you could write something like this (let Function
be a well-known interface of the JRE)
// Framework code
public Node buildTree(Function<BranchNode, Node, Node> branchNodeFactory) {
Node current = nextNode();
while (hasNextNode()) {
current = branchNodeFactory.call(current, nextNode());
}
return current
}
// MyDataNode.java
public class MyBranchNode implements BranchNode {
public MyBranchNode(Node left, Node right) { ... }
}
// Client code
Node root = buildTree(MyBranchNode::new);
See, no factory interfaces or classes. Many dynamic languages have first-class functions. Alas, this is not possible with Java 7 or earlier (implementing the same with factories is left as an exercise to the reader).
So, the alternative is not so much “use a different pattern”, but more “use a language with a better object model” or “don’t over-engineer simple problems”.
5