In this tutorial, we’ll learn and highlight the main differences between the Builder and the Factory patterns. These two particular patterns create significant confusion as they have similar intentions and often work together, making it more difficult to see their major differences. Additionally, they have several “flavors” that only add confusion.
2. Broad Explanation
The Factory and the Builder are creational patterns, and their primary responsibility is to provide a convenient and extensible way for object creation. However, they have different intentions and implementations. At the same time, they have many things in common. To understand these differences and commonalities better, let’s first review these two patterns in more detail.
The primary purpose of the Builder pattern is to help with the creation of a complex object. The complexity of an object requires a step-by-step creation and cannot, or is hard to, be reduced to a list of parameters. However, this pattern has two versions that differ dramatically in their goals and intentions.
3.1. Simple Builder
This version of the Builder pattern mainly aims to make object creation more convenient. This pattern is useful when an object has optional fields, and there might be too many combinations. Often this problem is resolved by telescopic constructors, which clutter the code and make it more error-prone. Let’s consider the following case where we used telescopic constructors:
The number of constructors would increase exponentially to cover all possible options. Also, if objects contain fields of the same type, it might be impossible to create all the variations because of overriding rules in most languages. The last thing is that it might result in hard-to-debug issues if we confuse the order of the parameters:
In this case, the Builder pattern would be a reasonable way to make this class more maintainable. Sometimes, creating a base object and finishing the configuration with setters is possible, which is a simple way to resolve the problem. However, we cannot use this for immutable objects. Also, if the object contains specific rules for the creation, we might not be able to check them, creating the object step-by-step:
A UserBuilder is a dedicated object that will store all the elements and create an object in one go. In this case, we can talk about the illusion of object creation in steps. Although the interface will create this illusion, the main power of the pattern is to make the entire object at once and ensure all the rules and constraints.
3.2. Classic Builder
This version of the pattern aims to provide a way to create a complex object in steps. The complexity emerges not from the number of parameters but from the object’s structure, which in most cases applies to Composite objects. Objects with a complex inner structure often cannot be expressed with the number of parameters. A department with sub-departments is a good application for a Builder.
This pattern is very flexible and can be used for the entire hierarchy of complex objects. At the same time, it can also be used for objects outside the hierarchy but with the same creation steps. For example, a maze and a maze map are both very complex objects and would have the same creational steps. However, they don’t belong to the same hierarchy.
The steps, or the rules, for creating an object are extracted to a Director class. This class contains complete knowledge of object creation. Usually, it involves graph traversing logic. If we want to translate an HTML web page into an object, we will use an algorithm, often recursive, rather than a recipe with several steps:
Thus, we have two types of this pattern. However, their goals and implementation are different. We can distinguish these patterns because the first one is used only to make it easier to create an object with many fields. The second is used for Composite objects to provide a way to create them step-by-step. We will use the second implementation to compare with the Factory pattern in this article.
The Factory pattern also has two implementations and one idiom, which isn’t considered a pattern but is widely used. Let’s find out what the differences are between them.
4.1. Factory Idiom
We want to use this idiom for two reasons: the single responsibility principle and code duplication. If the code for creation and picking an implementation is in our business logic, this breaks the single responsibility principle. Moving the instantiation logic to a separate method or class makes the code cleaner.
Another reason for using this idiom is to avoid code duplication. Keeping the code that creates an object consistent throughout our code base is a good idea. This also would provide a convenient way to change it in one place. Technically, the object itself can provide a method for convenient construction. Thus, it’s not necessary to create a dedicated class for this.
This idiom can be implemented by moving the code to a separate method or a class. Because it just uses the principles of a clean code and doesn’t create a hierarchy of factories, this is considered a programming idiom. This technique is helpful for simple cases when only one Factory is sufficient.
4.2. Factory Pattern
The Factory pattern is similar to the Template pattern. However, it creates an object rather than containing business logic. The main difference from the previous idiom is that this pattern uses polymorphism:
This pattern serves two goals, allowing a convenient way to change the factory and create an object. Also, it can encapsulate the creation of common objects. Additionally, the factories can accept parameters to be very flexible in object creation and behave like a wrapper over constructors.
4.3. Abstract Factory
The primary purpose of the Abstract Factory is to create an entire family the objects that are not in the same hierarchy. Creating UI elements for different styles or different models of furniture that would stylistically fit each other are good examples of this pattern:
5. Prerequisites and Intentions
Both of these patterns are used to make object creation more flexible and more convenient. However, they have different prerequisites and intentions.
Prerequisites for the Builder:
- Structurally complex objects
- The objects’ hierarchy follows the same steps or algorithms
Prerequisites for the Factory:
- Object creation is pretty straightforward
- Leverage polymorphism to provide an object of the required type
The main confusion with these patterns is that they have different implementations, and also, these patterns can work together and be used interchangeably in some cases.
This article highlighted the differences and similarities between the Factory and Builder patterns. These patterns are sometimes hard to distinguish as they have several implementations which can be merged. However, their main difference is the primary goal and the problems they resolve. The Factory provides a way to address the creation of different related objects. In contrast, the Builder helps to create an object with a complex internal structure.