September 8, 2020

Builder Design Pattern Implementation using Java Programming Language.

You can watch me live coding builder design pattern on youtube.

The Builder pattern is used for creation of instances where there are many properties. And, an instance can be a valid instance with most of the properties having no values at all.

One of the examples in Java is StringBuilder , we use append method to create a string and when we are done with the creation of string we call toString to get our String object.

In the example in this blog, I use a travel planner to showcase how a builder pattern can be used.

A travel planner has many parameters, but I am considering only 5, check-in date, check-out date, destination, number of guests and number of beds.

We can have default values for the properties. We can also do data validation checks in the code before creating final object.

You can read the entire source code here -> Builder Pattern Source Code

private Date checkInDate;
public ItineraryBuilder checkIn(final Date checkInDate){
    this.checkInDate = checkInDate;
    return this;
}

As, you can see above I have a created property checkInDate which is private and it has a builder function to update the value, and this function return the object which invoked this function back to the user.

With the help of this design, we can chain the functions to create an instance.

similarly all the properties have a private variable and a setter function.

public Itinerary travelPlan(){
    if(null == destination || destination.trim().isEmpty()) throw new IllegalArgumentException("Please provide destination.");
    final Itinerary travelPlan = new Itinerary ();

    travelPlan.checkInDate    = this.checkInDate;
    travelPlan.checkOutDate   = this.checkOutDate;
    travelPlan.noOfGuests     = this.noOfGuests;
    travelPlan.noOfBeds       = this.noOfBeds;
    travelPlan.destination    = this.destination;

    return travelPlan;
}

Then that builder class has a function to get a well formed instance of our target class.

We do data validation and create an object and return the created object.

final Itinerary travelPlan = (new Itinerary.ItineraryBuilder())
                                 .checkIn(new Date())
                     .checkOut(new Date())
                     .destination("Maldives")
                     .noOfGuests(1)
                     .noOfBeds(1)
                     .travelPlan();

As shown in the code above, you can see that we are able to use method chaining to create an instance of Itinerary class.

Entire source code :-

import java.util.Date;

public class Itinerary {
    private    Date checkInDate;
    private    Date checkOutDate;
    private    int  noOfGuests;
    private    int  noOfBeds;
    private    String destination;

    public Date checkInDate(){
        return this.checkInDate;
    }

    public Date checkOutDate(){
        return this.checkOutDate();
    }

    public int noOfGuests(){
        return this.noOfGuests;
    }

    public int noOfBeds(){
        return this.noOfBeds;
    }

    public String destination(){
        return this.destination;
    }
   
    @Override
    public String toString(){
        final StringBuilder message = new StringBuilder();
    int count = 0;

    message.append(++count).append(". ").append("Check In Date :- ").append(this.checkInDate).append("\n");
    message.append(++count).append(". ").append("Check Out Date :- ").append(this.checkOutDate).append("\n");
    message.append(++count).append(". ").append("Number Of Guests :- ").append(this.noOfGuests).append("\n");
    message.append(++count).append(". ").append("Number Of Beds :- ").append(this.noOfBeds).append("\n");
    message.append(++count).append(". ").append("Destination :- ").append(this.destination).append("\n");

    return message.toString();
    }

    static class ItineraryBuilder {
        private Date checkInDate;
    public ItineraryBuilder checkIn(final Date checkInDate){
        this.checkInDate = checkInDate;
        return this;
    }

        private Date checkOutDate;
    public ItineraryBuilder checkOut(final Date checkOutDate){
        this.checkOutDate = checkOutDate;
        return this;
    }

        private int noOfGuests ;
    public ItineraryBuilder noOfGuests(final int noOfGuests){
        this.noOfGuests = noOfGuests;
        return this;
    }

        private int noOfBeds;
    public ItineraryBuilder noOfBeds(final int noOfBeds){
        this.noOfBeds = noOfBeds;
        return this;
    }

        private String destination;
    public ItineraryBuilder destination(final String destination){
        this.destination = destination;
        return this;
    }

    public Itinerary travelPlan(){
        if(null == destination || destination.trim().isEmpty()) throw new IllegalArgumentException("Please provide destination.");
        final Itinerary travelPlan = new Itinerary ();

        travelPlan.checkInDate    = this.checkInDate;
        travelPlan.checkOutDate   = this.checkOutDate;
        travelPlan.noOfGuests     = this.noOfGuests;
        travelPlan.noOfBeds       = this.noOfBeds;
        travelPlan.destination    = this.destination;

        return travelPlan;
    }


    }
}

Code to test the Builder Class :-

import java.util.Date;

public class ItineraryTest{
    public static void main(String[] args){
        final Itinerary travelPlan = (new Itinerary.ItineraryBuilder())
                                 .checkIn(new Date())
                     .checkOut(new Date())
                     .destination("Maldives")
                     .noOfGuests(1)
                     .noOfBeds(1)
                     .travelPlan();
       System.out.println("Current Travel Plan");
       System.out.println(travelPlan);
    }
}