Builder Design Pattern – Creational Patterns

Builder Design Pattern comes under the creational design pattern, it is used to construct complex object step by step and finally, it will return the complete object. The logic and process of object creation should be generic so that you can use it to create a different concrete implementation of the same object type.

Builder Design Pattern

This pattern simplifies the construction of the complex objects and it hides the details of the object’s construction from the client caller code. When you using this pattern, remember you have to build one step at a time means you have to break object construction login into multiple phases unlike other patterns such as abstract factory, factory method pattern build the object in a single step.

“Separate the construction of a complex object from its representation so that the same construction process can create different representations” –According to GoF Patterns

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Patterns“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use an author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

UML class diagram for the Builder Pattern

Let’s see the following class diagram for the Builder Pattern. It illustrates the component classes and interfaces for this pattern.

Builder Design Pattern

Let’s see these classes and objects participating in this pattern are:

Builder (LoanBuilder)

  • This is an abstract class or interface and it specifies an abstract interface for creating parts of a Product object

ConcreteBuilder (CarLoanBuilder, HomeLoanBuilder, PersonalLoanBuilder)

  • These are concrete classes and constructs and assembles parts of the product by implementing the Builder interface
  • ConcreteBuilder defines and keeps track of the representation it creates
  • It provides an interface for retrieving the product

Director (LoanManager)

  • It constructs an object using the Builder interface

Product (Loan)

  • It represents the complex object under construction. ConcreteBuilder builds the product’s internal representation and defines the process by which it’s assembled
  • It includes classes that define the constituent parts, including interfaces for assembling the parts into the final result

Applicability

Let’s see the common problems where you should apply the Builder Pattern.

  • In the enterprise application, you can apply Builder Pattern where object creation has done by using multiple steps. In each step you do some unit of process, in this process, you set some required parameters and some optional parameters and after the final step, you will get a complex object.
  • The “Builder” pattern is an object creation software design pattern. The intention is to abstract the steps of construction so that different implementations of these steps can construct different representations of objects. Often, the builder pattern is used to build products in accordance with the composite pattern.

Pros of the Builder Pattern

The following pros of using the Builder pattern:

  • It provides you with complete isolation between the construction and representation of an object.
  • The Builder pattern allows you to construct the object in the multiple phases, so you have greater control over the construction process.
  • This pattern provides flexibility to vary an object’s internal representation.

Cons of the Builder Pattern

The following cons of using the Builder pattern:

  • The builder pattern is verbose and requires code duplication as Builder needs to copy all fields from Original or Item class.

Examples of Builder Pattern Implementation

In the Spring Framework, you can see the implementation of the builder design pattern transparently in some functionalities. As below classes are based on the Builder Design Pattern in the Spring Framework.

  • EmbeddedDatabaseBuilder
  • AuthenticationManagerBuilder
  • UriComponentsBuilder
  • BeanDefinitionBuilder
  • MockMvcWebClientBuilder

Sample Implementation of Builder Design Pattern

Let’s discuss a business case related the banking as I discussed throughout this book, here I am taking one business case related to Loan product of any bank, I am using Builder Design Pattern to solve the problems of banking loan example. So main problem in this example is that the customer of the bank who wants a loan, to perform the steps to get a loan either Home Loan or Car Loan and that process has multiple steps, so to maintain correct order by customer is difficult. So, how will we address this in real life? We will contact a loan manager who knows the process to construct a loan.

The second problem was that we require different types of loans, such as home loan, car loan, and personal loan. So next, we will contact to loan manager of the bank who specializes in building specific types of loans. A loan manager knows how to put things together with actual documentation and verification processes for a loan. For example, a home loan manager knows all about documentation and verification for home loan application. Similarly, a car loan manager knows all about documentation and verification for car loan application. So from now on, whenever we need a loan, the loan manager will direct a builder to build the loan.

In our application, we can model the loan manager by creating a LoanManager class. Then we can model the builders by first creating a LoanBuilder interface and then builder classes, such as HomeLoanBuilder and CarLoanBuilder that implement the LoanBuilder interface. Here, notice that we have added a layer of abstraction by providing an interface. This is because we do not want our loan manager to be tied with a particular loan builder. The loan manager should be able to direct any builder that implements the LoanBuilder interface to build a loan. This will also allow us to later add new builders without making changes to the existing application code.

Step 1: Create an interface Item representing loan item.

LoanBuilder.java

package com.doj.patterns.creational.builder;

public interface LoanBuilder {
	void loanApply();
	void loanApproval();
	void loanSanction();
	Loan loanDisburse();
}

Step 2: Let’s create concrete classes implementing the LoanBuilder interface

CarLoanBuilder.java

package com.doj.patterns.creational.builder;

/**
 * @author Dinesh.Rajput
 *
 */
public class CarLoanBuilder implements LoanBuilder {
	private Loan loan;
	
	public CarLoanBuilder() {
		super();
		this.loan = new Loan();
	}

	@Override
	public void loanApply() {
		loan.setLoanAmount(Double.valueOf(500000));
		loan.setLoanName("Car Loan");
		System.out.println("CarLoanBuilder: Applied for Car Loan for Amount 500000");
	}

	@Override
	public void loanApproval() {
		loan.setApproved(true);
		System.out.println("CarLoanBuilder: Car Loan has been Approved...");
	}

	@Override
	public void loanSanction() {
		loan.setLoanAccount(30000l);
		loan.setLoanFee(Double.valueOf(5000));
		loan.setRoi(Double.valueOf(10.3));
		System.out.println("CarLoanBuilder: Car Loan has been processed and sanctioned...");
		System.out.println("Details: Total processing fee 5000 and interest rate 10.3 and loan account 30000...");
	}

	@Override
	public Loan loanDisburse() {
		return this.loan;
	}

}

PersonalLoanBuilder.java

package com.doj.patterns.creational.builder;

/**
 * @author Dinesh.Rajput
 *
 */
public class PersonalLoanBuilder implements LoanBuilder {
	private Loan loan;
	
	public PersonalLoanBuilder() {
		super();
		this.loan = new Loan();
	}

	@Override
	public void loanApply() {
		loan.setLoanAmount(Double.valueOf(200000));
		loan.setLoanName("Personal Loan");
		System.out.println("PersonalLoanBuilder: Applied for Personal Loan for Amount 200000");
	}

	@Override
	public void loanApproval() {
		loan.setApproved(true);
		System.out.println("PersonalLoanBuilder: Personal Loan has been Approved...");
	}

	@Override
	public void loanSanction() {
		loan.setLoanAccount(20000l);
		loan.setLoanFee(Double.valueOf(2000));
		loan.setRoi(Double.valueOf(14.3));
		System.out.println("PersonalLoanBuilder: Personal Loan has been processed and sanctioned...");
		System.out.println("Details: Total processing fee 2000 and interest rate 14.3 and loan account 20000...");
	}

	@Override
	public Loan loanDisburse() {
		return this.loan;
	}

}

HomeLoanBuilder.java

package com.doj.patterns.creational.builder;

/**
 * @author Dinesh.Rajput
 *
 */
public class HomeLoanBuilder implements LoanBuilder {
	
	private Loan loan;
	
	public HomeLoanBuilder() {
		super();
		this.loan = new Loan();
	}

	@Override
	public void loanApply() {
		loan.setLoanAmount(Double.valueOf(4000000));
		loan.setLoanName("Home Loan");
		System.out.println("HomeLoanBuilder: Applied for Home Loan for Amount 4000000");
	}

	@Override
	public void loanApproval() {
		loan.setApproved(true);
		System.out.println("HomeLoanBuilder: Home Loan has been Approved...");
	}

	@Override
	public void loanSanction() {
		loan.setLoanAccount(10000l);
		loan.setLoanFee(Double.valueOf(40000));
		loan.setRoi(Double.valueOf(8.30));
		System.out.println("HomeLoanBuilder: Home Loan has been processed and sanctioned...");
		System.out.println("Details: Total processing fee 40000 and interest rate 8.3 and loan account 1000...");
	}

	@Override
	public Loan loanDisburse() {
		return this.loan;
	}
	
}

Step 3: Let’s create LoanManager class to build the LoanBuilder.

LoanManager.java

package com.doj.patterns.creational.builder;

/**
 * @author Dinesh.Rajput
 *
 */
public class LoanManager {
	private LoanBuilder loanBuilder;

	public LoanManager(LoanBuilder loanBuilder) {
		super();
		this.loanBuilder = loanBuilder;
	}
	
	public Loan buildLoan(){
		this.loanBuilder.loanApply();
		this.loanBuilder.loanApproval();
		this.loanBuilder.loanSanction();
		return this.loanBuilder.loanDisburse();
	}
}

Step 4: BuilderPatternMain uses LoanManager to demonstrate builder pattern.

BuilderPatternMain.java

package com.doj.patterns.creational.builder;

/**
 * @author Dinesh.Rajput
 *
 */
public class BuilderPatternMain {

	public static void main(String[] args) {
		LoanManager loanManager = new LoanManager(new HomeLoanBuilder());
		Loan homeLoan = loanManager.buildLoan();
		System.out.println(homeLoan);
		System.out.println("--------------------------------------------------\n");
		
		loanManager = new LoanManager(new CarLoanBuilder());
		Loan carLoan = loanManager.buildLoan();
		System.out.println(carLoan);
		System.out.println("--------------------------------------------------\n");
		
		loanManager = new LoanManager(new PersonalLoanBuilder());
		Loan personalLoan = loanManager.buildLoan();
		System.out.println(personalLoan);
	}

}

Step 5: Let’s run the above demo class and verify the output.

HomeLoanBuilder: Applied for Home Loan for Amount 4000000
HomeLoanBuilder: Home Loan has been Approved...
HomeLoanBuilder: Home Loan has been processed and sanctioned...
Details: Total processing fee 40000 and interest rate 8.3 and loan account 1000...
Loan [roi=8.3, loanAmount=4000000.0, loanName=Home Loan, loanAccount=10000, loanFee=40000.0, approved=true]
--------------------------------------------------

CarLoanBuilder: Applied for Car Loan for Amount 500000
CarLoanBuilder: Car Loan has been Approved...
CarLoanBuilder: Car Loan has been processed and sanctioned...
Details: Total processing fee 5000 and interest rate 10.3 and loan account 30000...
Loan [roi=10.3, loanAmount=500000.0, loanName=Car Loan, loanAccount=30000, loanFee=5000.0, approved=true]
--------------------------------------------------

PersonalLoanBuilder: Applied for Personal Loan for Amount 200000
PersonalLoanBuilder: Personal Loan has been Approved...
PersonalLoanBuilder: Personal Loan has been processed and sanctioned...
Details: Total processing fee 2000 and interest rate 14.3 and loan account 20000...
Loan [roi=14.3, loanAmount=200000.0, loanName=Personal Loan, loanAccount=20000, loanFee=2000.0, approved=true]

Previous
Next

2 Comments

  1. Leonel Aquino May 31, 2019
  2. Dinesh Rajput June 3, 2019