This blog post describes how to use the abstract factory design pattern.
This post is part of the Design Patterns in Java Series. Check out the full list of covered patterns there.
Before you read on, I highly recommend you first read my previous post on the factory method pattern. The abstract factory pattern is essentially a generalisation of the factory method, so it makes sense to understand the simpler case first.
Why Should You Use the Abstract Factory Design Pattern?
The abstract factory is used when we need to create families of products without having to depend on concrete classes.
Essentially, you would use this pattern to package a bundle of related products.
You would then create each product using a factory method.
The headline photo of this article is supposed to suggest the idea of packaging things together.
What is an Abstract Factory?
Here’s the definition from the Head First Design Patterns book:
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
In other words, the abstract factory creates a package of multiple products, whereas the factory method creates one product.
In this way, I like to think of the abstract factory as a kind of generalisation of the factory method pattern.
Furthermore, we’re controlling the package creation step so we ensure that clients get packages with matched products. In the absence of the pattern, clients might put together products that don’t make sense to bundle together.
You’ll better understand the pattern with the class diagram below. This builds nicely on the diagram from the factory method pattern.
Let’s go back to our computer manufacturing business. In the factory method example, we were only building laptops, namely normal laptops and gaming laptops. Let’s also assume that we are currently operating in the US.
Since our business is going well, we want to extend our product range to computer servers. Similarly, we will offer a normal server and a more powerful gaming server as products.
As we would also like to cut manufacturing costs, we plan on opening a new company branch in Poland. We want the Poland branch to take care of building the gaming laptops and gaming servers as these are more expensive to manufacture.
Therefore, we have two groups of products, namely the normal range of computers and the gaming range. The former is built in the US, the latter is built in Poland.
Coming back to the definition of the abstract factory, the related products in this case would be the laptops and the servers.
Abstract Factory Class Diagram
In this diagram, ComputerFactory
is our interface for creating our bundle of related products. The two concrete factory implementations are USComputerFactory
and PolandComputerFactory
.
The USComputerFactory
creates packages of NormalLaptop
s and NormalServer
s, while the PolandComputerFactory
creates packages of GamingLaptop
s and GamingServer
s.
Pros
- similar to the factory method, the pattern avoids tight coupling between the client and object creation.
- allows bundling related product objects and promises compatibility between them.
Cons
- if the abstract factory interface changes (i.e.
ComputerFactory
in the example above), then all factories would need to be updated.
- increased code complexity due to the new classes.
Abstract Factory vs Factory Method
Congratulations! You’re now familiar with both factory patterns. Let’s put them in contrast.
Well, we’ve already established that both of these patterns create objects.
Additionally, both patterns decouple client code from concrete types as clients are only concerned with the abstract types.
The difference is that on one hand, the factory method creates objects via inheritance—since creation is delegated to subclasses. On the other hand, the abstract factory relies on object composition to create a bundle of objects. Each object is created via its own factory method.
How Can You Implement the Abstract Factory Pattern?
Let’s implement in Java the class design from the previous section.
Abstract Factory Pattern Java Code Example
The Laptop
and Server
interfaces would be:
The classes implementing the Laptop
interface are:
The classes implementing the Server
interface are:
Next, the ComputerFactory
interface is the actual abstract factory that we’re trying to illustrate.
The USComputerFactory
is a concrete implementation of the ComputerFactory
interface and returns a package of a NormalLaptop
object and a NormalServer
object:
The PolandComputerFactory
is another concrete implementation of the ComputerFactory
interface and returns a package of a GamingLaptop
object and a GamingServer
object:
Lastly, the client code can be:
The output is then:
Summary
In conclusion, the three main key points are:
-
Abstract factory creates families of related products.
-
The pattern decouples client code from concrete products.
-
Abstract factory pattern ensures compatibility between packaged products.