Abstract Factory is one of the 23 “Gang Of Four” design patterns. So it's got to be important. But when I was asked to produce an actual use case, I came up blank. Your favorite search engine will find you any number of examples, but all of the ones I inspected were bogus. Is it time to put this pattern to pasture?
Everyone knows what a factory method is. You use it to construct an instance without calling the constructor. Like
Locale loc = Locale.forLanguageTag("en-US");
instead of the (now deprecated)
Locale loc = new Locale("en", "us");
Here, the factory method is clearly superior to calling the constructor. When a second client needs the "en-US"
locale, the factory method can return the previously constructed instance. A constructor must construct a new instance.
But that's not the Factory Method pattern. The Factory Method pattern is one of 23 patterns in the seminal book Design Patterns - Elements of Reusable Object-Oriented Software, by four inspiring authors, Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. (The author team and the book are often referred to as the “Gang of Four” or GoF, a reference to an important group of Chinese revolutionaries. I've always found this pretty weird given that these two sets of people have nothing in common other than their size.)
Here is the diagram for the Factory Method from the GoF book, in a notation that has since evolved into UML:
I can never remember any of these patterns without a concrete example. For Factory Method, my concrete example is Collection.iterator()
. Each concrete class implementing Collection
implements the iterator
method to yield an instance of a class implementing Iterator
. An ArrayList
produces one kind of Iterator
, and LinkedList
produces another kind.
As you can see, not every factory method falls into the Factory Method pattern. You need a hierarchy of classes, each of which produces an instance from a companion hierarchy.
Twenty years ago, I wrote a book Design and Patterns for teaching object-oriented design to students with a background in programming and data structures. In the book, I illustrated many of the GoF patterns with examples from the Java API and had tables such as the following:
Name in Design Pattern | Actual Name |
---|---|
Creator | Collection |
ConcreteCreator | A subclass of Collection |
factoryMethod () | iterator() |
Product | Iterator |
ConcreteProduct | A subclass of Iterator (which is often anonymous) |
As it turns out, Swing is a good source of examples for design patterns. I illustrated the Composite pattern with AWT Component
/Container
and explained why, for historical reasons, JComponent
/JContainer
don't quite match the pattern. JScrollPane
is a fantastic example for the Decorator pattern.
Name in Design Pattern | Actual Name |
---|---|
Component |
Component |
ConcreteComponent |
JTextArea |
Decorator |
JScrollPane |
method() |
A method of the Component interface. For example, the paint
method paints a part of the decorated component and the
scroll bars. |
This worked very nicely in 2003. At the time, teaching a bit of Swing was considered a reasonable use of lecture time. Students remembered the patterns through the examples. They no longer labeled everything that was decorative an instance of Decorator, or everything that appeared strategic as an example of Strategy.
It stopped working ten years later, when nobody wanted to learn Swing anymore. I tried with JavaFX and Android, but those APIs are not actually as nicely thought out as Swing was. And students didn't care about JavaFX either. And Android was too much of a pain. And anyway, object-oriented design is no longer viewed as the magic bullet, as it was in 2003. And that is surely a good thing.
I considered rewriting the book in JavaScript and adapt patterns to functional programming. But I never did. JavaScript is considered toxic in the academic world.
Back to abstract factories. Suppose you have a “family of products” that you need to generate. The classic example for such a family of products is user interface elements: windows, scrollbars, buttons, and so on. And suppose further that there are several such families, and you need to pick one of them as the program starts. In the classic example, maybe your program launches and finds it must use Motif. Or Presentation Manager. Unless you are of a certain age, you probably never heard of either.
The solution that GoF proposes is to make an abstract factory class with creator methods for each of the “products”, such as createWindow
, createScrollbar
, createButton
, and so on. And concrete factories for Motif and Presentation Manager and, in more modern times, Win32 and GTK and MacOS.
The scenario isn't very plausible because a GUI program doesn't typically wake up to poke around what toolkit it should use. And if it did, you'd be surprised how much variation there is in GUI toolkits. One of them may have a class for scroll bars, and in another, scroll bars are just a property of a text area. All the cross-platform toolkits that I know make the programmer create windows, buttons, and so on, by calling a plain old constructor. No pluggable factory in sight.
So, my question is whether Abstract Factory actually occurs in the wild. A pattern that follows this structure:
Of course, we all hear jokes about factory madness in Java frameworks. “I have a Java joke. Actually, I have a factory that builds abstract jokes...” Perhaps for good reason—just look at the javax.naming.spi.ObjectFactoryBuilder
or RequestProcessorFactoryFactory.RequestProcessorFactory. But those are not examples of the Abstract Factory pattern. There are no families of products in sight.
What about javax.xml.parsers.DocumentBuilderFactory
? Another crazily overengineered thing. You use a DocumentBuilderFactory
to build a DocumentBuilder
to build a Document
—the thing that you actually want when you work with XML. But again, not an example of Abstract Factory. No family of products at either level. All a DocumentBuilderFactory
can create is a DocumentBuilder
. And all a DocumentBuilder
can create is a Document
.
Go ahead, search for real life example of abstract factory design pattern. My first hits were
And on and on it goes. Not an actual real life example in sight. Pure dross. ChatGPT can do just as well. In fact, when I asked it, I first got bullshit about cars and SUVs, document editors, and 3D game engines. When I said, no, a real example from an actual software system, it produced:
I asked specifically what the concrete creators and products are in Swing. ChatGPT told me that the LookAndFeel
classes are the creators with methods createButton
, createScrollBar
(!), and createTextField
. I looked inside WindowsLookAndFeel
, and to nobody's surprise, there is no createButton
method inside. After all, the whole point of Swing is to draw these buttons to mimic the native look and feel, instead of using the native controls.
What about libconfig? The whole point of libconfig is to use a configuration file like this one, which the library's creators tout as more compact and readable than XML. To nobody's surprise, there are no INI, JSON, or XML parsers.
This StackOverflow question plaintively asks: “Please provide me any real life example where I must implement abstractFactory pattern? ”
Do the answers deliver? Sadly no. One respondent, with more upvotes than the question, states “Abstract Factory is a very central design pattern for Dependency Injection (DI)”. Really? Why? Show me the factories for families of products!
If you had such factories, all implementing a common interface, you could use DI to select one of them. But without factories that create families of products, the Abstract Method pattern doesn't apply.
The contributor who tirelessly debunks that and other fanciful theories doesn't do so well in term of upvotes.
At the end the SO article says “Highly active question. Earn 10 reputation (not counting the association bonus) in order to answer this question.” Should I try?
Comments powered by Talkyard.