JavaDesign patterns

Builder

The design problem

Builder pattern is a creational design pattern used to separate complex object construction from its representation and can be used to create objects step by step with a specified structure. Let’s imagine the following situation.

You decide to write computer games where users create and develop their own heroes. Over the course of the game, they can change heroes’ characteristics like personal data, appearance, physical skills, equipment and type of hero. The tasks are to create a module that will provide a flexible way of hero creation or change. The first idea is to describe one hero class with many constructors and majority parameters where every parameter is responsible for the corresponding characteristic. But such an approach will fail when you want to expand heroes’ characteristics because you have to spend much time rebuilding the hero class. This is where builder pattern is suitable. Instead of one hero class, you describe several new classes to make our hero module scalable and the save object immutable.

The Builder pattern

To create an object, you need to call the builder methods in turn. You do not need to run all the steps, only those that are necessary for the production of an object of a certain configuration.

The same construction step may differ for different variations of the produced objects. You can create several builder classes that perform the same steps in different ways in the same building process and as a result, you can get various objects.

Builder pattern has the following components :
  • Builder interface describes steps of product construction. Each complex object requires the service of a Builder class to generate object instances.

  • ConcreteBuilder implements Builder to make the required representation of the product. It will construct and assemble the parts of the final product and provide the interface to retrieve the final product. This is the main component, which keeps track of the specific representation of the product.

  • Director manages the object creation process using the Builder class, and it will not directly create and assemble the final complex object.

  • Product is the complex object constructed using the concrete builder class which contains the final user-requested representation.

An example: building a hero



public class HeroBuilder implements Builder {

    private String type;
    private int health;
    private int power;

    public void setType(String type) {
        this.type = type;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public void setPower(int power) {
        this.power = power;
    }

    public Hero getResult() {
        return new Hero(type,health,power);
    }
}


public class Hero {

    private String type;
    private int health;
    private int power;

    public Hero(String type,int health,int power) {
        this.type = type;
        this.health = health;
        this.power = power;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
       this.type = type;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public int getPower() {
        return power;
    }

    public void setPower(int power) {
        this.power = power;
    }
}

public class Creator {

    public void createHuman(Builder builder) {
        builder.setType("Human");
        builder.setHealth(100);
        builder.setPower(500);
    }

    public void createOrc(Builder builder) {
        builder.setType("Orc");
        builder.setHealth(1000);
        builder.setPower(5000);
    }

    public void createElf(Builder builder) {
        builder.setType("Elf");
        builder.setHealth(500);
        builder.setPower(1000);
    }
}

public class Client {
    public static void main(String[] args) {
        Creator creator = new Creator();

        HeroBuilder builder = new HeroBuilder();
        creator.createElf(builder);
        Hero hero = builder.getResult();

        System.out.println(">> Hero created : " + hero);
        creator.createHuman(builder);
        Hero hero2 = builder.getResult();
        System.out.println(">> Hero created 2: " + hero);
    }
}

Conclusion

Builder pattern is applicable when:

  • the object cannot be constructed in one call. This might be the case when the product is immutable or contains complex object graphs, e.g. with circular references.

  • you have one build process that should build many different kinds of products.

How did you like the theory?
Report a typo