Software Design Patterns: Factories Are Not Builders
The difference between Factory and Builder design patterns

Design patterns are useful when you need a typical guideline for common problems in Software Engineering, and having knowledge of their existence will help you find a solution that best fits your problem.
I've seen factories being implemented like builders and vice versa, and implementations like this can cause confusion and prevent us from using their full power. I hope this article helps you to find the difference between these two patterns and their common implementations.
Problem
Sometimes we have to build components that need to show some kind of information and it adapts depending on the amount of information that has been given.
To give you a basic example of a common problem I've designed this kind of Bottom Sheet component with different types of "style" depending on the content provided.

First Solution: Factory Method Pattern
The Factory Method pattern is a creational design pattern responsible for providing a simple interface for object initialization, with no need to expose any concrete classes. Basically, is an object responsible for initializing other objects.
As another example, you can use a switch
containing multiple styles for this object, like .small
, .medium
and .large
We know that this switch can become really complex depending on how much the project scales, so if this happens you can create more factories containing isolated logic for your styles. As an example, you can extract the .large
logic to a LargeBottomSheetFactory
.
Second Solution: Builder Pattern
The Builder pattern is a creational design pattern that is more common to see in languages like Java than Swift. The main idea is that it allows us to build Products step by step using methods to set up an object the way we want and one single method at the end to build it, without exposing the object creation/configuration and properties.
As you can see, all methods except for the build()
returns Self
(aka the Builder itself). Doing it like this enables us to create a "Chained" builder implementation. The idea behind the builder is that the component will build depending on how much information you pass to the builder.
The Builder Pattern also allows us to create Director
classes. These classes are basically objects that have builders as a dependency and offer a simplified interface for other objects to build a Product without using the builder directly, as you can see in the example below.
Which one should I use?
If you want to create an object with many possible configurations but don’t need to have all the information at the moment to build it, you can use the Builder Design Pattern. This pattern provides a simple interface to hide complex object tasks, allows us to privatize a lot of public properties, and reduces the need to keep a mutable state.
When you need to encapsulate the logic for initializing some object, you can also opt to use the Factory Design Pattern. This pattern guarantee that you can simplify the way you create an object across the code, avoid delegating the creation to a subclass, and avoid code duplication since you don't need to pass all of its dependencies over and over again. You have all centralized in one place, the factory.
Conclusion
Both patterns are creational design patterns that provide us mechanisms for object initialization with flexibility and scalability, without the need to access the object properties or initializer directly, but as you saw, they’re not the same. Of course, there’s no ‘best one’, so you will choose those who fit best your problem.
Now, you should be able to identify and apply these patterns correctly.