Creational Pattern: Builder
This article discusses how complex objects can be represented and constructed without coupling the two operations.
What is it?
The builder pattern reduces the amount of code needed to create objects. Therefore, if you have a complex thing to build, you can simplify this process using the builder pattern. A composite or an aggregate object is what a builder generally makes.
The builder pattern encapsulates the process of building a complex object, separating its representation from its construction. This allows us to create different models with the same construction process. In Java speak, this means creating objects of other classes that may share the same construction process.
Class Diagram
The class diagram includes the following entities:
- Builder
- Concrete Builder
- Director
- Product
Example
Continuing with our example of airplanes, let’s say that the construction of an aircraft involves three steps:
- the making of the cockpit
- then the engine
- and finally, the wings
WEveryn imagines that every aircraft requires the above in our hypothetical world three steps in our hypothetical world. However, a passenger aircraft could have an added step of making bathrooms in the plane. The steps represent the construction process from our formal definition. The product is an aircraft, but we can make representations of it in different ways. For example, we should be able to produce an F-16 and a Boeing-747 using the same construction process.
Let’s take a look at the code now. First, we’ll start with the abstract interface for our AircraftBuilder
class. Next, each builder contains methods that can be overridden by concrete builders depending on if they will include that part in the final product variant they are responsible for building.
Now we’ll implement two concrete builders, one for F-16 and one for Boeing-747.
For simplicity, we have provided the skeleton of the builders and skipped individual implementation of each method. It F16Builder
doesn’t override the buildBathrooms
method because there aren’t any bathrooms in the F-16 cockpit. The Boeing 747’s creator overrides the bathroom method since a Boeing 747 has bathrooms for passengers.
The Director
class is responsible for recording the process or algorithm required to create an aircraft, like the specific order in which different parts are made. The director is like a builder of the aircraft. The finished product is returned to him by the builders.
Notice that we can pass in the builder of our choice and vary the aircraft product (representation) to be either an F-16 or a Boeing-747. In our scenario, the builders return different supertypes, but this may not be the case if they return products that aren’t very similar.
The client will apply the pattern in this way:
The AircraftBuilder
interface hides how an aircraft gets built. The client is unaware of the classes F16Engine
and F16Cockpit
that are used to create Boeing-747s.
Skipping the Director
The Builder pattern is often used without the director. Instead, the client can directly instantiate the builder and invoke the required methods to get a product for itself. This is a common antidote for telescoping constructors. For example, imagine a class with too many attributes, but some of them can be set to be optional. In such a case, you can invoke the builder only to set the required attributes and create a product.
Other Examples
- The Java API exposes a
StringBuilder
class that doesn’t strictly conform to the GoF builder pattern, yet it can still be thought of as an example of it. The StringBuilder class provides an append method that returns a new string by appending characters from the original string. - Another hypothetical example could be creating documents of type pdf or HTML.
Here’s an example:
The above method can appear in a client or server code, and different document types can be built by passing a different DocumentBuilder
into the method. We could derive a HtmlDocumentBuilder
and a PdfDocumentBuilder
from the abstract class DocumentBuilder
.
Caveats
The builder and abstract factory patterns have similar goals but approach them differently. For example, the builder pattern creates objects one step at a time, whereas the abstract factory returns an object in one go.
Other articles in the Creational Pattern series
- Creational Pattern: Singleton
- Creational Pattern: Prototype
- Creational Pattern: Factory Method
- Creational Pattern: Abstract Factory
My other publications: https://ercindedeoglu.github.io/