Java Design Pattern: Builder Pattern

A valid alternative to contructors



Today we are going to talk about a creational pattern that in many situations can represent a useful alternative to the construction of the objects using the constructors: the Builder Pattern.

The need to introduce alternative mechanisms to those provided by Java for the creation of objects is originated from the fact that sometimes the structures are very complex and it is not always trivial to set up a well-formed constructor. Think of the cases in which the number of attributes is very high or the cases in which there are attributes that may not even be valued. The probability of making a mistake by writing the constructor by hand is very high.

The goal is to separate the creation of the object from its representation. In this way, the algorithm for creating the object is independent from the various parts that make up the object and how they are assembled.

The creation of the instances and their management are separated from each other so the program becomes simplest.

A very interesting aspect is that these mechanisms allow you to create an object step by step, checking its suitability at each step (think about when we want to build an object with data from the results of a parser) and above all it allows us to hide the control logic that would perhaps have been present in the possible manufacturer.

Let's give a definition:

The Builder Pattern is used to create instances of very complex objects with telescopic constructors in the simplest way

Let's look at the UML diagram of the Builder Pattern:

Builder pattern UML

Let's analyze in detail every component:

  • Product: it defines the type of object that will be generated from the Builder Pattern;
  • Builder: this abstract class defines the various steps needed in order to correctly create objects. Each method is generally abstract and implementations are provided by concrete subclasses. The getProduct () method is used to return the final product. Sometimes the Builder is replaced by an interface;
  • ConcreteBuilder: there may be different ConcreteBuilder concrete subclasses. These subclasses gives the mechanisms for the creation of complex objects;
  • Director: the Director class controls the algorithm for the objects creation. When it is instanciated, its constructor is invoked. It contains a parameter that indicates which ConcreteBuilder has to be used for creating objects. During the creation process, the various methods of the ConcreteBuilder are called and at the end of the operations, the getProduct() method is used in order to get the final product;

Let's look a possible structure in Java

Director

public class Director {
  public Director(Builder builder){
    builder.buildPart1();
    builder.buildPart2();
    builder.buildPart3();
    builder.getProduct();
  }
}

Builder

public abstract class Builder {
  public abstract void buildPart1();
  public abstract void buildPart2();
  public abstract void buildPart3();
  public abstract Product getProduct();
}

ConcreteBuilder

public class ConcreteBuilder extends Builder {
  private Product product;
  public ConcreteBuilder(){
    product=new Product();
  }
  @Override
  public void buildPart1() {
    product.setAttr1("attr1");
  }
  @Override
  public void buildPart2() {
    product.setAttr2("attr2");
  }
  @Override
   public void buildPart3() {
    product.setAttr3("attr3");
  }
  @Override
  public Product getProduct() {
    return product;
  }
}

Product

public class Product {
  public String attr1;
  public String attr2;
  public String attr3;
  public String getAttr1() {
    return attr1;
  }
  public void setAttr1(String attr1) {
    this.attr1 = attr1;
  }
  public String getAttr2() {
    return attr2;
  }
  public void setAttr2(String attr2) {
    this.attr2 = attr2;
  }
  public String getAttr3() {
    return attr3;
  }
  public void setAttr3(String attr3) {
    this.attr3 = attr3;
  }
}

Let's have a look to a possible use of the pattern. The example that I'm going to show comes from the book Effective Java written by Joshua Bloch. We state that in this particular case, the abstract Builder class is not strictly indispensable. It can be added as an exercise without radically changing the structure presented below.

import java.util.List;
     public class Animal {
     private final String id;
     private String name;
     private String pedigreeName;
     private String owner;
     private String race;
     private String residence;
     private Boolean isVaccinated;
     private Boolean isChampion;
     private List sons;
     private Sex sex;
     private Double weight;
     private Double height;
     public Animal(String name, String pedigreeName, String id, String owner, String race, String residence, Boolean isVaccinated, Boolean isChampion, List sons, Sex sex, Double weight, Double height) {
        this.name = name;
        this.pedigreeName = pedigreeName;
        this.id = id;
        this.owner = owner;
        this.race = race;
        this.residence = residence;
        this.isVaccinated = isVaccinated;
        this.isChampion = isChampion;
        this.sons = sons;
        this.sex = sex;
        this.weight = weight;
        this.height = height;
     }
     public Animal(String id, String name, String pedigreeName) {
        this.name = name;
        this.pedigreeName = pedigreeName;
        this.id = id;
     }
     public Animal(String id, String owner, String race, String residence) {
        this.id = id;
        this.owner = owner;
        this.race = race;
        this.residence = residence;
     }
     public Animal(String id) {
        this.id = id;
     }
     public enum Sex {
        MALE,
        FEMALE
     }
 }

Now we use the pattern

import java.util.List;

public final class AnimalBuilder {
    private String id;
    private String name;
    private String pedigreeName;
    private String owner;
    private String race;
    private String residence;
    private Boolean isVaccinated;
    private Boolean isChampion;
    private List<String> sons;
    private Animal.Sex sex;
    private Double weight;
    private Double height;

    private AnimalBuilder(String id) {
        this.id = id;
    }

    public static AnimalBuilder newBuilder(String id) {
        return new AnimalBuilder(id);
    }

    public AnimalBuilder name(String name) {
        this.name = name;
        return this;
    }

    public AnimalBuilder pedigreeName(String pedigreeName) {
        this.pedigreeName = pedigreeName;
        return this;
    }

    public AnimalBuilder owner(String owner) {
        this.owner = owner;
        return this;
    }

    public AnimalBuilder race(String race) {
        this.race = race;
        return this;
    }

    public AnimalBuilder residence(String residence) {
        this.residence = residence;
        return this;
    }

    public AnimalBuilder isVaccinated(Boolean isVaccinated) {
        this.isVaccinated = isVaccinated;
        return this;
    }

    public AnimalBuilder isChampion(Boolean isChampion) {
        this.isChampion = isChampion;
        return this;
    }

    public AnimalBuilder sons(List<String> sons) {
        this.sons = sons;
        return this;
    }

    public AnimalBuilder sex(Animal.Sex sex) {
        this.sex = sex;
        return this;
    }

    public AnimalBuilder weight(Double weight) {
        this.weight = weight;
        return this;
    }

    public AnimalBuilder height(Double height) {
        this.height = height;
        return this;
    }

    public Animal build() {
        return new Animal(name, pedigreeName, id, owner, race, residence, isVaccinated, isChampion, sons, sex, weight, height);
    }
}

An object can now be instanciates as follow.

Animal pluto2=AnimalBuilder.newBuilder("0000001")
        .name("0000001")
        .pedigreeName("PlutoSecondo")
        .owner("Marco Rossi")
        .race("labrador")
        .residence("Via x")
        .isVaccinated(true)
        .isChampion(false)
        .sons(null)
        .sex(Animal.Sex.MALE)
        .weight(40.5)
        .height(30.0)
        .build();

We can find different advantages in the use of this creational pattern, in fact we can create clone objects or very similar objects minimizing the code that has to be written. The used method is similar to the one shown below, referring to the builder created before:

Animal animal3A = animalBuilder.build();
Animal animal3AClone = animalBuilder.build();
Animal animal3B = animalBuilder.sex(Animal.Sex.FEMALE).build();

Here we create two identical objects and an object similar to the previous two, but with opposite sex. A very important advantage is that of concentrating class validation in a single method and therefore obtaining almost immutable objects.

Va precisato che la versione presentata è leggermente diversa da quella presentata nel modello originale. L'unico svantaggio dell'utilizzo del pattern è il fatto che vada necessariamente definita una classe builder per ogni oggetto, aumentando nettamente il tempo di sviluppo.

Must be said that the shown version is slightly different from the one shown in the original example. The only disadvantage of using the pattern is the fact that a builder class must necessarily be defined for each object, significantly increasing the development time.

A lot of IDEs have plugin for the management of builders. Personally, I use the IntelliJ plugin  Builder Generator.

By the way, in my opinion,it is always useful to have tools like this available wink

 
 
Alessio Mungelli

Alessio Mungelli

Computer Science student at UniTo (University of Turin), Network specializtion, blogger and writer. I am a kind of expert in Java desktop developement with interests in AI and web developement. Unix lover (but not Windows hater). I am interested in Linux scripting. I am very inquisitive and I love learning new stuffs.

 
 
 

Related Posts

Strings in JavaScript: What they are and how to use them

In this tutorial we are going to explain what strings are and how they are used in JavaScript. The tutorial is intended for people who are learning to program in…

Dates in local format with Javascript

In the articles we have about dates in JavaScript we were missing one about how to create dates in local format with JavaScript. That is to say, being able to…

Formatting hours in Javascript

Continuing with the set of articles that talk about internationalisation elements, like the previous one where we talked about relative dates in JavaScript, we will see in this one how…

Request data with prompt in JavaScript

After having published several articles about how to manipulate arrays and dates, today I will publish a post that some of you will find too basic and others will find…

Relative dates in JavaScript

One of the interesting things about the internationalisation library represented in the Int object is the handling of relative dates in Javascript. This handling allows us to represent a date…

How to access webcam and grab an image using HTML5 and Javascript

We often use webcams to broadcast video in real time via our computer. This broadcast can be viewed, saved and even shared via the Internet. As a rule, we need…

The JavaScript forEach loop

We have already talked about how to handle some of loops  types in Javascript including for, for-in and for-off loops. In the case of today we are going to see how…

What are React Hooks and what problems they solve

Working with React, - and before the release of Hooks in version 16.8 -  there was always the possibility to create components in three different ways based on a number of…

Flattening arrays in JavaScript

When we are handling arrays that are arrays or have multiple dimensions it can be very useful to know how to flatten arrays in JavaScript. That is to say, to…

How to populate an array with random numbers in JavaScript

Some of you might think that what we explained in the article on how to populate an array with numbers, apart from the didactic part, would not have much applicability…

How to populate an array with numbers in JavaScript

Populate an array with numbers in JavaScript The first step is to initialise the array. So today we are going to see a simple way to do it and see how…

Top Javascript Libraries and Frameworks Part 2

What are JavaScript frameworks?   JavaScript frameworks are application frameworks that allow developers to manipulate code to meet their particular needs. Web application development is like building a house. You have the option…

We use our own and third-party cookies to improve our services, compile statistical information and analyze your browsing habits. This allows us to personalize the content we offer and to show you advertisements related to your preferences. By clicking "Accept all" you agree to the storage of cookies on your device to improve website navigation, analyse traffic and assist our marketing activities. You can also select "System Cookies Only" to accept only the cookies required for the website to function, or you can select the cookies you wish to activate by clicking on "settings".

Accept All Only sistem cookies Configuration