Learn the Builder Design Pattern
This is the 5th post in a series on design patterns.
Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.
Consider a complex object requiring step-by-step initialization of many fields and nested objects. These initialization codes are usually buried inside a monstrous constructor with a lot of parameters or scattered all over the client code.
Let’s look at how to create a Laptop object. In order to construct a simple laptop, you will need a CPU, LED screen, keyboard, touchpad, hard drive, and RAM. However, what if we wanted a powerful laptop with WiFi, Bluetooth, and other latest technologies such as SSD, touch screen, dedicated graphics, DVD ROM, etc?
The simplest solution is to extend the Laptop class and create subclasses for each combination of parameters. Eventually, though, you’ll have quite a few subclasses. Adding a new parameter, such as an HD camera, will require growing this hierarchy even more.
Alternatively, there is a way to avoid breeding subclasses. You can create a giant constructor right in the base Laptop class with all the parameters that control Laptop objects. Although this approach eliminates the need for subclasses, it leads to another problem. As a result, most of the parameters will be unused, making the constructor call ugly.
Builder Design Pattern
As part of the Builder design pattern, you separate the object construction code out of its own class and move it into separate objects called builders.
Object construction is organized into a set of steps like addSSD, addRAM, etc. A series of these steps are required to create an object using a builder object. The critical part is that you don’t have to call all of the steps. Only the steps that are necessary for producing a particular configuration of an object can be called.
To go one step further, you can extract calls to the builder steps you use to construct a product into a separate class called Director. The director defines the order in which the building steps should be executed, whereas builders implement the steps. It’s not strictly necessary to create a Director class, you can always call the steps in a specific order directly from the client code.
UML Class Diagram
Not familiar with UML Class Diagram? I have written a detailed post on the UML Class diagram.
Implementation steps
- The Builder interface declares the steps of building a product that is common to all builders.
- Concrete Builders (LaptopBuilder) implements the construction steps in a different way.
- The finished product (Laptop) is the end result.
- The Director class defines the order in which construction steps are called, so specific configurations of products can be created and reused.
- The client associates one of the builder objects with the director via the director’s constructor parameters. Then the director uses the builder object for all further construction.
Source Code Implementation
The Builder interface declares product construction steps that are common to all types of builders.
Concrete Builders (LaptopBuilder) provides a different implementation of the construction steps.
The product (Laptop) is the resulting object.
Enum used by Director class for LED type.
The Director class defines the order in which to call construction steps.
The BuilderClient associate one of the builder objects with the director via the director’s constructor parameters.
When To Apply Builder Design Pattern
- Build your application with the Builder design pattern to eliminate the telescopic constructor. A telescopic constructor is one in which a class has multiple constructors, each of which calls another constructor in the hierarchy that has more parameters than itself, providing default values for the extra parameters. The next constructor does the same until there are no more left.
- You should use the Builder pattern if you want your code to create different representations of some products.
- Build complex objects progressively using the Builder design pattern.
Pros of Builder Design Pattern
- It is possible to construct objects step-by-step, defer construction steps, or run steps recursively.
- The same construction code can be reused when building various representations of products.
- Complex construction code can be separated from business logic.