Builder Pattern – Creational

Builder Pattern – Creational

Reading Time: ~ 5 minutes

In this post, I’d like to talk about the Builder Pattern. This pattern is part of the Creational grouping in which other patterns such as Factory and Singleton are also a part of.

For what do we use the Builder Pattern?

Sometimes we might need to have objects that work in the same way, however, have different components internally. Or we might just need two objects that are similarly built, but of course not the same. For those situations, we can make use of the Builder Pattern.

The Builder does get rid of cases such as an explosion of subclasses to deal with the different configurations that an object can have; cases where classes have a big amount of constructors or cases where a class has a constructor with many parameters to try to deal with all possible configurations.

Most important of all the Builder pattern separates the (maybe complex) construction of an object, from the representation of this object.

Structure

Here I’d like to define two ways that this is encountered: the formal way and another way that you see used quite a lot and in my opinion, it is slightly different than the formal definition.

Formal Structure

Here is the basic structure of the Builder Pattern (if you need a refresher on UML check this post and this post) in the way it is defined in the GoF Patterns Book:

PlantUML Syntax:<br />
hide members<br />
interface Builder<br />
Director o-right- Builder<br />
Builder <|– ConcreteBuilder ConcreteBuilder .right.> Product<br />

Builder

The Builder is the interface which will  define which defines the parts that the constructor accepts

Concrete Builder

This is the implementation of the builder interface. It will assemble the object accordingly to how it defines the object to be implemented

Director

It is simply the class that makes the use of the Builder in order to construct and get the object.

Product

The final object which the Builder is tasked to build.

Example Scenario

Let us use the scenario where we want to build a car. Now a car has the same structure: it has wheels, a transmission, a chassis, a motor, doors, etc. However, each of those components can vary itself in different ways. This is where the builder pattern shines!

If we make use of the SportCarBuilder variant or the RegularCarBuilder variant we are in both cases getting a Car out of the builder!

Implementation

In this example, I won’t define all subtypes used in the code, but just the main parts.

Alright so let’s define the Builder Interface:

public interface CarBuilder {
    public void setEngine (Engine engine);
    public void setTransmission(Transmission transmission);
    public void setWheels (Wheel wheel);
    public void setChassis(Chassis chassis);
}

Alright with that we can define the concrete builder:

public class CarBuilderImpl implements CarBuilder {
    private Engine engine;
    private Transmission transmission;
    private Chassis chassis;
    private Wheel wheel;

    @Override
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    @Override
    public void setTransmission(Transmission transmission) {
        this.transmission = transmission;
    }

    @Override
    public void setChassis(Chassis chassis) {
        this.chassis = chassis;
    }

    @Override
    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }

    public Car getResult() {
        return new Car(engine, transmission, chassis, wheel);
    }
}

Note that the builder contains a method that will create the object and return it.

Now our director which knows how the car type should be constructed:

public class Director {

    private Builder builder;

    public Director(){
        this.builder = new CarBuilderImpl();
    }

    public Car construct(CarType type){
        switch (type){
            case SPORT:
                return constructSportsCar();
            case REGULAR:
            default:
                return constructCityCar();
        }
    }
    private Car constructSportsCar() {
        builder.setEngine(new Engine(3.0, 0));
        builder.setTransmission(Transmission.AUTOMATIC);
        builder.setChassis(new SportsChassis());
        builder.setWheels(new SportsWheel());

        return builder.getResult();
    }

    private Car constructCityCar() {
        builder.setEngine(new Engine(1.2, 0));
        builder.setTransmission(Transmission.MANUAL);
        builder.setChassis(new TownCarChassis());
        builder.setWheels(new RegularWheel());

        return builder.getResult();
    }
}

And finally, we can use the code we wrote. By passing a type to the Director.construct() method.

 

 

“Out in the Wild” Structure

Here is the basic structure of the Builder Pattern that you might come across while you work on your daily job or favorite open source code. They are quite similar, however, I find it nice to have an extra example:

PlantUML Syntax:<br />
hide members<br />
Director o-right- Builder<br />
Builder .right.> Product<br />

Builder

The Builder is the class that takes care of building the product object correctly and eventually returning it to the requester class.

You often see this class as an inner class from the Product Class itself, however, this is not a nice clean code approach. One should aim for 1 Class = 1 File.

Director

Just like the former case, this is simply the class that makes the use of the Builder in order to construct and get the object.

Product

The final object which the Builder is tasked to build.

Example Scenario

The scenario will be exactly the same as the above scenario but you will see the differences are in the code:

Implementation

First, we have the Builder itself which is not an interface and it will return a reference of itself so to allow the use of concatenation. It also makes use of the Fluent pattern which makes the code read more like a normal sentence.

public class CarBuilder {
    Engine engine;
    Transmission transmission;
    Wheel wheel;
    Chassis;

    public CarBuilder withEngine (Engine engine){
        /* Catch and throw illegal arguments here if you want to have certain guarantees */
        this.engine = engine;
        return this;
    };
    
    public CarBuilder withTransmission(Transmission transmission){
        /* Catch and throw illegal arguments here if you want to have certain guarantees */
        this.transmission = transmission;
        return this;
    };
    
    public CarBuilder withWheels (Wheel wheel){
        /* Catch and throw illegal arguments here if you want to have certain guarantees */
        this.wheel = wheel;
        return this;
    };
    
    public CarBuilder withChassis(Chassis chassis){
        /* Catch and throw illegal arguments here if you want to have certain guarantees */
        this.chassis = chassis;
        return this;
    };
    
    public Car build(){
        return new Car(this);
    };
}

Note that we have the method call build() which order the builder to do what is supposed to do if its named “builder”. It passes itself to the car builder and with that avoids long lists of parameters.

All the fields are also package-private which will make sense since the Car constructor will want to access these.

Now before a quick word about the Car object, let us show how the Director gets when we use the structure above instead the formal one:

public class Director {

    public Car construct(CarType type){
        switch (type){
            case SPORT:
                return constructSportsCar();
            case REGULAR:
            default:
                return constructCityCar();
        }
    }

    private Car constructSportsCar() {
        return new CarBuilder().withEngine(new Engine(3.0, 0))
                               .withTransmission(Transmission.AUTOMATIC)
                               .withChassis(new SportsChassis())
                               .withWheels(new SportsWheel())
                               .build();
    }

    private Car constructCityCar() {
        return new CarBuilder().withEngine(new Engine(1.2, 0))
                               .withTransmission(Transmission.MANUAL)
                               .withChassis(new TownCarChassis())
                               .withWheels(new RegularWheel())
                               .build();
    }
}

In my opinion, this is more concise.

Finally the car object. In this case, we can have the constructor set to something like package-private since it should only get accessed by the Builder. It also will get a builder and it unpacks on to its variables:

public class Car {
    private Engine engine;
    private Transmission transmission;
    private Wheel wheel;
    private Chassis;


    Car (CarBuilder builder){
        this.engine = builder.engine;
        this.transmission = builder.transmission;
        this.wheel = builder.wheel;
        this.Chassis = builder.chassis;
    }

   // Getters and setters
}

As you can see the car class can get what it needs and even perform some functions on the variables before assigning it to its own fields.

 

Conclusion

So this is the Builder pattern! Hope you could clarify your doubts or even learn something new. Please comment away  if you have any doubts or if I can help you with anything.

Leave your opinion, start a discussion, share an experience or just a compliment...

%d bloggers like this: