The REAL Builder Pattern

I have been reading about Design Pattern lately, and I ran across some articles about the Builder Pattern that are not accurate at all. Because of that, I decided to write a short article about what this pattern is and how to properly implement it. I will start by providing a short description of what this pattern is. I will follow that with some context by providing hypothetical usages for this pattern, and conclude with a (hopefully good) code example.

What is the Builder Pattern?

Even these bad articles got one thing right: The Builder Pattern is a Creational Pattern. This means that the pattern's main goal is to provide a reusable solution for creating objects. You may ask, why are there more than one creational pattern? Isn't invoking a class constructor enough? Well... yes and no.

Why use Builder Pattern?

Experts (people who know more than me) have determined that using one of these creational patterns is preferred over invoking the constructor of a class directly. In order to keep this short, I am not going to get in depth regarding why creational patterns are preferred over invoking constructors directly. So, suffice to say that invoking constructors directly is fine for very simple objects needed to solve simple problems. As the complexity of one or both of these things increases, the need for a better solution than invoking the constructor directly is more and more apparent. Creational Patterns are not (necessarily) in competition with each other. Therefore, you could argue that there isn't one pattern that is better than another. They just simply have different usages. Because this article is just about the Builder Pattern, I am going to focus strictly on it. The main advantage of this pattern is that it allows a complex object to be built step by step.

Consider an automobile assembly line. The vehicle being assembled is not built all at once. It is put together in stages. I am not an expert in automotive manufacturing, but I can assume you would start by taking a chassis and adding components to it: motor, transmissions, drive train, exhaust system, floor, body, electrical system (wiring), seats, windshield, windows, etc. The point is that the vehicle is put together piece by piece, component by component, until a fully-functional vehicle rolls out the factory. You could say that after all pieces are put together, you roll out an instance of vehicle.

As a side note, always remember to narrow the scope or responsibility of a class to a single thing (Single Responsibility Principle, or the 'S' in SOLID). For example, a motor is made of many smaller components. Therefore, if I was to model a vehicle class, instead of making every single part that composes an engine an attribute of vehicle, I would create a motor class that would encapsulate all these. This way, the vehicle class would only have a single "motor" attribute to be concerned with. This approach will make your code cleaner, and thus more maintainable. It will also make your Builder less verbose.

Implementing the Pattern

In my opinion, including a builder as a static nested class is probably the best approach.
The image above is a representation of a Person class and its builder. When an instance of person needs to be created, the attributes of Person are passed to its builder. Once the builder's client passes the required attributes of person to it, it can invoke createPerson() in order to obtain an instance of the Person class.

Let's use the Vehicle class example and use the Builder Pattern to create an instance of it. The first thing we are going to do is to identify all of the required components and all the optional components. All required components must be declared as final. In the case of my simple Vehicle class, engine is required but stereo is optional. Therefore,


public class Vehicle
{
    private final Engine engine; // final for immutability
    private final StereoSystem stereo; // final for immutability
    ...
    public static class Builder
    {
        private final Engine engine; // REQUIRED
        private StereoSystem stereo; // OPTIONAL

        public Builder(Engine engine)
        {
            this.engine = engine;
        }
        ...
    }
}
The attributes of Vehicle are made final for immutability (topic not covered here). In the Builder class, the distinction between final and non-final attributes is necessary to distinguish between optional and required components. Required components, since they are made final, cannot be changed once the object is instantiated. Therefore, the value must be set via the Builder's constructor. Non-final attributes can be, in turn, resolved later, if needed.

When using the Builder pattern, setter methods take a unique form. Setter method must return the current instance of builder


public Builder addStereo (StereoSystem stereo)
{
    this.stereo = stereo;
    return this;
}
Why is this? In order to be able to add additional components to the builder object PRIOR to creating an instance of the object being built; in this case, before a vehicle object is instantiated.

Since we are putting the responsibility on the builder to provide an instance of Vehicle, we must prevent its constructor to be invoked directly (bypassing the builder) by making the constructor private. Now, even though Builder is a member of the Vehicle class, it doesn't have access to the Builder's internal attributes. This problem is solved by passing Builder to the Vehicle private constructor.


private Vehicle (Builder builder)
{
    stereo = builder.stereo;
    engine = builder.engine;
}

Lastly, the builder must provide a "build" method that returns an instance of the object being created. In this case, an instance of Vehicle.


public Vehicle build ()
{
    return new Vehicle(this); // Vehicle instance finally committed to memory
}
My Vehicle class with its Builder, altogether, would look something like this:

public class Vehicle
{
    private final Engine engine;
    private final StereoSystem stereo;

    private Vehicle (Builder builder)
    {
        stereo = builder.stereo;
        engine = builder.engine;
    }

    public static class Builder
    {
        private final Engine engine; // REQUIRED
        private StereoSystem stereo; // OPTIONAL

        public Builder(Engine engine)
        {
            this.engine = engine;
        }

        public Builder addStereo (StereoSystem stereo)
        {
            this.stereo = stereo;
            return this;
        }

        public Vehicle build ()
        {
            return new Vehicle(this); // Vehicle instance finally committed to memory
        }
    }
}
The simplest way to use the builder is to "daisy-chain" the calls and create the object all at once. For instance:

public static void main(String [] args)
{
    // Engine and stereo creation omitted.
    // Assume they are properly instantiated
    Vehicle myCar = new Vehicle.Builder(engine)
        .addStereo(stereo).build();
}
However, you can follow the assembly line illustration and assemble it in parts

public static void main(String [] args)
{
    // Engine and stereo creation omitted.
    // Assume they are properly instantiated
    Builder builder = new Vehicle.Builder(engine);

    // Do something here...

    builder.addStereo(stereo);

    // Do something else...

    Vehicle myCar = builer.build();

}
Don't let other articles fool you. This is the REAL way to implement the Builder Pattern. As always, your feedback, positive or negative, is greatly appreciated.

Comments

Popular posts from this blog

Combining State and Singleton Patterns to Create a State-Machine

The Beauty of the Null Object Pattern

Java Keywords (Part I): Creating Classes