Do Abstract Factories Occur in the Wild?

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?

Factory Methods and the Factory Method Pattern

.webp

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:

.gif

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.

Design and Patterns

.jpg

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.

Abstract Factories

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:

.gif

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?

Conclusion

  1. The concept of software design patterns is an undisputed success. There really are patterns that can be profitably learned and applied in a variety of settings.
  2. Vehicles, animals, vending machines, pizzas, and so on, do not make for compelling examples. Learning the backstory can be tedious. The rules of the game are arbitrary and don't provide useful guidance.
  3. If you want to illustrate anything in software design, stick to things that people actually implement. Data structures, file systems, persistence, data transfer, search. Shopping carts, invoices, credit card transactions, UI toolkits, can be fair game too provided you have hands-on implementation experience with the domain.
  4. A design pattern is a very specific recipe. Not everything decorative is a Decorator. Not everything that seems abstract and produces things is an Abstract Factory.
  5. No canonical catalog is perfect. The GoF book was published in 1994. It would be a miracle if all of its 23 design patterns withstood the test of time. Their track record is far better than that of the Chinese 四人帮 (Gang of Four), but there are foundational patterns that they missed, and some of their discoveries ended up not living up to their promise. It seems that Abstract Factory is one of them.

Comments powered by Talkyard.