In this tutorial, we’ll discuss the Factory pattern and all its flavors. This is a widely used pattern with its version for each specific problem. There are two main types of the Factory pattern, the Factory pattern itself and the Abstract Factory pattern. They are closely related and have similar goals.
Additionally, we have a simplified version of this pattern, which is often considered an idiom. However, it is important to discuss it in the context of the Factory pattern to understand the differences and applications.
2. Factory Method (Factory Idiom)
Let’s start with the simplest version of the Factory pattern: the Factory Method. 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 contain a method for convenient construction:
However, it is possible to create a dedicated class for this:
This 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. Technically, having several Factories without a common interface would still be considered an idiom, especially if the logic is associated with a class instead of an object:
This technique is helpful for simple cases when one Factory is sufficient or runtime polymorphism isn’t required.
3. 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 encapsulates 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:
In the example above, a Factory produces various products based on the passed parameter. While we use a simple value as a parameter, it might be more complex and represented by a dedicated class.
4. Abstract Factory Pattern
The primary purpose of the Abstract Factory is to create an entire family the objects that aren’t 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:
Imagine that we’d like to create different furniture sets and ensure each piece fits the set:
One Factory is responsible for creating all the products in a set. This way, by providing an application with a Factory, we can ensure that the sets aren’t mixed up. Also, it allows changing the implementations of the products in the entire application by just switching the Factory implementation.
5. Abstract Factory vs. Parametrized Factory
Two Factory versions are often confused: Abstract Factory and Parametrized Factory. The reason is that both of them produce a set of different products. Usually, Parametrized Factory creates products that differ by state, but it could provide a different implementation.
The Abstract Factory produces a set of related but, at the same time, different products. In terms of object-oriented design, it means that the products would have different interfaces. This was the case for the example with the furniture Factory above. Let’s try to turn a Parametrized Factory into an Abstract Factory:
Although we are creating different types of ice cream, we use the same interface for all of them. This means that the difference is hidden from the user and insignificant to the interaction with the object. The Parametrized Factory was sufficient for the case, and the Abstract Factory is an overly complex solution to this problem.
However, if these types of ice cream had significant differences in their interfaces and behavior, which we should highlight for a client, the Abstract Factory would be a good fit for it. In this case, the structure would look like this, similar to the example with a furniture Factory above:
This logic can also work the other way around. We can consider a context where we can use our furniture pieces on the same interface, for example, in the context of transportation. This would mean that we can turn our initial Abstract Factory into Parametrized Factory only because we don’t need the products to have different interfaces:
While choosing the correct pattern, we should consider the products and the context where they’ll be used. Thus, the Abstract Factory is used where we need to have the differences between products explicit, and the Parametrized Factory is where it isn’t necessary.
In this article, we learned the differences between the Factory Method, the Factory, and the Abstract Factory. The Factory Method is a great tool to clean up the code and keep it simple. The Factory helps us to leverage polymorphism and be prepared for future changes. On top of the previous benefits, the Abstract Factory ensures that we are working with the set of related objects.
These similar techniques have slightly different goals and shouldn’t be confused. The patterns can make the code less complicated, more flexible, and more understandable for everyone working on it. However, it takes time to understand their application and where each would be more useful.