Abstract Factory Design Pattern — A Factory of Factories

Jeremy Lee
5 min readNov 9, 2021

--

Imagine this: you are a software engineer in charge of implementing a furniture simulator software. Your client has specified that the application must be able to display 20 distinct types of furniture (e.g. chair, table, desk, drawers), and for each type of furniture, they can be made from 3 different types of materials (marble, wood or steel). From this requirement alone, we would need to create 20 x 3 = 60 different concrete classes! Does it mean we have to create 60 different constrctors in our client-side code, 1 for each concrete class?

Fortunately, situations like these are common, and there exists a design pattern by the Gang of Four that helps to make our code much more maintainable.

Abstract Factory Pattern to the rescue!

The Abstract Factory Pattern is a design pattern that allows us to create factories of objects. It is implemented as an interface that exposes creation methods that are inherited and shared across all the concrete classes implementing it. Let us take a look at the class diagram below for a better illustration.

For the sake of simplicity, let us assume our shop currently only sells chairs and tables, and only steel and wood furniture are currently supported. By having FurnitureFactory interface, we can then declare and implement concrete classes ChairFactory and TableFactory , both of which expose the methods to create steel and wood furniture. These methods, createSteelFurnitureand createWoodFurniture, will be implemented by these concrete factories to produce their respective products.

How does this work?

The underlying principles behind the Abstract Factory Pattern are polymorphism and inheritance.

Polymorphism allows us to declare the 2 creation methods createSteelFurniture and createWoodFurniture to return SteelFurniture and WoodFurniture respectively, and the concrete class to be instantiated would ultimately depend on the concrete factory.

Inheritance allows us to keep our code maintainable, by declaring a set of creation methods in the Abstract Factory class that are the same across all the concrete factory classes. The set of creation methods will not change significantly or often, as it is bound by the Abstract Factory interface, which acts as a contract.

So what?

At this point, you might still be doubtful about the usefulness of the Abstract Factory Pattern. So what if we declare an interface with a contract of creation methods? At the end of the day, won’t we still be creating the same number of concrete classes?

Well, yes, but suppose your client now wants to add a new type of furniture to the shop. They want the application to be able to support cupboards. With the Abstract Factory Pattern, we can simply extend our code as per the diagram below:

Updated diagram which includes CupboardFactory

Client-side code will not be impacted, as the client only has knowledge of the 2 creation methods that we expose: createSteelFurniture and createWoodFurniture as declared in out FurnitureFactory . This hence ensures that our code abides by the Open-Closed Principle, where the code is readily extendable but closed for modifications.

In addition, this design strictly adheres to the Single Responsibility Principle. Each factory is only responsible for creating 1 type of furniture, and each method is only responsible for creating that furniture of a specified material. This is another core tenet of software engineering, as it helps to keep our code readable for other developers.

However…

As observed, implementing the Abstract Factory Pattern involves creating many interfaces and abstract classes, which would otherwise be unnecessary if we simply solve this problem the naive way by creating only the concrete classes. This can make the codebase larger, especially if there are many combinations of concrete products.

Applicability in real life

Personally, I think the Abstract Factory Pattern works really well, particularly because of how it strictly follows the Open-Closed Principle. In a project to create a static program analyser that takes in a sample program and answers queries based on that program, I made use of the Abstract Factory Pattern to model parts of the query.

Specifically, there are 2 query clauses which share the same characteristics: the Uses clause and Modifies clause. These clauses each have 2 variants, 1 being Clause(int, int/string) and the other being Clause(string, int/string). Seeing the similarly between these 2 clauses, I hence applied the Abstract Factory Pattern for the creation of these objects.

Below is a class diagram explaining the relations between these classes:

Below are code snippets from my project (only the relevant parts are shown):

Abstract Factory exposing creation methods
Concrete factory UsesRelationObjectFactory
Concrete factory ModifiesRelationObjectFactory

Conclusion

The Abstract Factory Pattern impliclty enforces the Single Responsibility Principle and the Open-Closed Principle. These are two core tenets of software engineering that every software developer should know at the back of their hands. If you have not tried using the Abstract Factory Pattern before, I urge you to give it a try! The next time you have a project that requires you to implement many families of objects, consider using the Abstract Factory Pattern. You will be surprised at how easy it is to navigate the codebase.

--

--