Builder pattern is used to hide the complexity of building complex objects from the client and also this pattern is responsible for building objects step-by-step.
This article demonstrates Builder pattern implementations in Java. Check the following examples.
Implementation
These are the common key points for implementing Builder pattern in Java.
- Create classes for the main items. These classes will have getter methods.
- Create builder classes, and implement a builder interface for these builders. Implement the setter methods in builder class.
- Create a function named “build()” (the name may change), which will create required object and return that.
- Additionally, we can introduce a producer, which will use the builder and create objects.
Examples
Here are a few examples of builder pattern implementation in Java programming language.
Example #1: Request Builder (Using inner Builder)
Here is a simple example of Builder pattern which uses an inner class as a builder.
Let’s consider implementing a request-sending package. We want to build the request step by step and then send it when the building is complete.
Request Class with Builder
In this process, we are using an inner class for implementing the Builder pattern. Here are the key points of the “Request” class –
- Create a class named “Request”.
- Create a static inner class named “Builder”. This class has methods for setting different values, and all these methods should have a return type of “Builder”.
- In the “Builder” class create a method named “build()”. In this method create a new object of type “Request”, and pass the current “Builder” object while object creation, like, “new Request(this)”.
- Create a method named “send()” in the “Request” class. Write code for sending the request inside the method.
package com.bigboxcode.designpattern.builder.request;
import java.util.HashMap;
enum RequestType {
GET,
POST,
PUT,
PATCH,
DELETE,
}
public class Request {
private String url;
private RequestType type;
private HashMap<String, String> header;
private HashMap<String, String> body;
private Request(Builder builder) {
this.url = builder.url;
this.type = builder.type;
this.header = builder.header;
this.body = builder.body;
}
public void send() {
System.out.println("Sending Request...");
System.out.println("URL: " + url);
System.out.println("Type: " + type);
System.out.println("Headers: " + header);
System.out.println("Body: " + body);
// Write functional code to send request
}
public static class Builder {
private String url;
private RequestType type;
private HashMap<String, String> header = new HashMap<String,String>();
private HashMap<String, String> body =new HashMap<String,String>();
public Builder url(String url) {
this.url = url;
return this;
}
public Builder type(RequestType type) {
this.type = type;
return this;
}
public Builder header(String key, String value) {
this.header.put(key, value);
return this;
}
public Builder body(String key, String value) {
this.body.put(key, value);
return this;
}
public Request build() {
return new Request(this);
}
}
}
Demo
Here is the process of how to use the builder pattern implementation –
- For using the Builder pattern implementation, use “new Request.Builder()” as the “Builder” inner class is static.
- Then call the required methods and pass the value. We can call the methods one by one, and in any sequence.
- At last call the “build()” method, this will make sure that the request object is constructed properly.
- Call the “send()” method at the end, to send the request.
package com.bigboxcode.designpattern.builder.request;
public class Demo {
public static void main(String[] args) {
// Build the request step by step
Request request = new Request.Builder()
.url("https://bigboxcode.com/request-test")
.type(RequestType.POST)
.header("X-AUTH-TOKEN", "someTokeHere")
.header("X-SOME-HEADER", "someRandomHeaderValueHere")
.body("unit_id", "99")
.body("code", "88C3ABK")
.build();
// Send request
request.send();
}
}
Output
Output of the above code will be as below.
Sending Request...
URL: https://bigboxcode.com/request-test
Type: POST
Headers: {X-SOME-HEADER=someRandomHeaderValueHere, X-AUTH-TOKEN=someTokeHere}
Body: {code=88C3ABK, unit_id=99}
Example #2: Vehicle Builder
Let’s consider another example where we build/create objects for different vehicles, like, cars or plane,s etc. We will use the builder pattern so the complex vehicle objects can be created easily.
First, create the concrete item classes.
Car Concrete Class
Create a concrete class for the item Car. Follow these important points for this class –
- Declare variables for storing information like, wheel, engine, seat, etc.
- In the constructor accept param so that we can set the values of all class variables.
- Add getter methods for the class variables. No need to implement the setter methods.
- Add any other method as per requirement, there is no strict rule for that.
package com.bigboxcode.designpattern.builder.vechicle;
public class Car {
private int wheel;
private int engine;
private int seat;
private int door;
private boolean interior;
public Car(int noOfWheel, int noOfEngine, int noOfSeat, int noOfDoor, boolean interior) {
this.wheel = noOfWheel;
this.engine = noOfEngine;
this.seat = noOfSeat;
this.door = noOfDoor;
this.interior = interior;
}
public int getWheel() {
return wheel;
}
public int getEngine() {
return engine;
}
public int getSeat() {
return seat;
}
public int getDoor() {
return door;
}
public boolean isInterior() {
return interior;
}
public String toString() {
return "Car: Wheel -> " + wheel + " | Engine -> " + engine + " | Seat -> " + seat + " | Door -> " + door + " | Interior -> " + interior;
}
}
Plane Concrete Class
Create a concrete class for Plane. Follow all the same rules mentioned above for the Car class.
package com.bigboxcode.designpattern.builder.vechicle;
public class Plane {
private int wheel;
private int engine;
private int seat;
private int door;
private int wing;
private boolean interior;
public Plane(int noOfWheel, int noOfEngine, int noOfSeat, int noOfDoor, int wing, boolean interior) {
this.wheel = noOfWheel;
this.engine = noOfEngine;
this.seat = noOfSeat;
this.door = noOfDoor;
this.wing = wing;
this.interior = interior;
}
public int getWheel() {
return wheel;
}
public int getEngine() {
return engine;
}
public int getSeat() {
return seat;
}
public int getDoor() {
return door;
}
public int getWing() {
return wing;
}
public boolean isInterior() {
return interior;
}
public String toString() {
return "Plane: Wheel -> " + wheel + " | Engine -> " + engine + " | Seat -> " + seat + " | Door -> " + door + " | Wing: " + wing + " | Interior -> " + interior;
}
}
Vehicle Builder Interface
We need to create a vehicle builder interface, to make sure that all the vehicle builder classes have the same interface –
- Create an interface named “VehicleBuilder”.
- Declare methods for setting values (following the class variables from Car and/or Plane class).
package com.bigboxcode.designpattern.builder.vechicle;
public interface VehicleBuilder {
void addWheel(int noOfWheel);
void addEngine(int noOfEngine);
void addSeat(int noOfSeat);
void addInterior();
void addDoor(int noOfDoor);
void addWing(int noOfWing) throws Exception;
}
Car Builder Class
Let’s create a builder class for the car. Follow the import points mentioned below –
- Create a class named “CarBuilder”.
- This class has the same class variables(wheel, engine, door, etc.) as the “Car” class.
- Implement the builder interface “VehicleBuilder”.
- As part of the “VehicleBuilder” interface implementation, implement the setter methods for the class variables (wheel, engine, seat, etc).
- Add a method named “build()”, this method creates a new object of “Car” class and returns that.
package com.bigboxcode.designpattern.builder.vechicle;
public class CarBuilder implements VehicleBuilder {
private int wheel;
private int engine;
private int seat;
private boolean interior;
private int door;
@Override
public void addWheel(int noOfWheel) {
System.out.println("Add " + noOfWheel + " wheels");
this.wheel += noOfWheel;
}
@Override
public void addEngine(int noOfEngine) {
System.out.println("Add " + noOfEngine + " engine");
this.engine += noOfEngine;
}
@Override
public void addSeat(int noOfSeat) {
System.out.println("Add " + noOfSeat + " Seat");
this.seat = noOfSeat;
}
@Override
public void addInterior() {
System.out.println("Add interior");
this.interior = true;
}
@Override
public void addDoor(int noOfDoor) {
System.out.println("Add " + noOfDoor + " door");
this.door += noOfDoor;
}
@Override
public void addWing(int noOfWings) throws Exception {
throw new Exception("Can not add wings");
}
public Car build() {
Car car = new Car(wheel, engine, seat, door, interior);
return car;
}
}
Plane Builder Class
Create a builder class for Plane. Name the class “PlaneBuilder”.
Follow the same/similar steps mentioned for the “CarBuilder”.
package com.bigboxcode.designpattern.builder.vechicle;
public class PlaneBuilder implements VehicleBuilder {
private int wheel;
private int engine;
private int seat;
private boolean interior;
private int door;
private int wing;
@Override
public void addWheel(int noOfWheel) {
System.out.println("Add " + noOfWheel + " wheels");
this.wheel += noOfWheel;
}
@Override
public void addEngine(int noOfEngine) {
System.out.println("Add " + noOfEngine + " engine");
this.engine += noOfEngine;
}
@Override
public void addSeat(int noOfSeat) {
System.out.println("Add " + noOfSeat + " Seat");
this.seat = noOfSeat;
}
@Override
public void addInterior() {
System.out.println("Add interior");
this.interior = true;
}
@Override
public void addDoor(int noOfDoor) {
System.out.println("Add " + noOfDoor + " door");
this.door += noOfDoor;
}
@Override
public void addWing(int noOfWings) throws Exception {
System.out.println("Add " + noOfWings + " wing");
this.wing += wing;
}
public Plane build() {
Plane plane = new Plane(wheel, engine, seat, door, wing, interior);
return plane;
}
}
Vehicle Producer Class
Create a producer for the vehicles. Follow the important points mentioned below –
- Create a class named “VehicleProducer”.
- Create a method for building Car, named “carBuilder”. Create another for Plane, named “planeBuilder”.
- These producer methods accept a builder object, set values, and then return the builder.
package com.bigboxcode.designpattern.builder.vechicle;
public class VehicleProducer {
public CarBuilder buildCar(CarBuilder carBuilder) {
carBuilder.addWheel(4);
carBuilder.addEngine(1);
carBuilder.addDoor(4);
carBuilder.addSeat(4);
carBuilder.addInterior();
return carBuilder;
}
public PlaneBuilder buildPlane(PlaneBuilder planeBuilder) {
planeBuilder.addWheel(3);
planeBuilder.addEngine(2);
planeBuilder.addDoor(4);
planeBuilder.addSeat(120);
planeBuilder.addInterior();
try {
planeBuilder.addWing(2);
} catch (Exception e) {
throw new RuntimeException(e);
}
return planeBuilder;
}
}
Demo
For using the Builder pattern use the following instructions-
- Create an object of the producer class “VehicleProducer”. This producer will be used to generate objects of both Car and Plane class.
- Create builder object of “CarBuilder” and/or “PlaneBuilder”.
- Pass the object to the builder method of the “VehicleProducer” object. This will populate the values of the builder class.
- Call the “build()” method of the builder class to generate the desired object.
package com.bigboxcode.designpattern.builder.vechicle;
public class Demo {
public static void main(String[] args) {
VehicleProducer vehicleProducer = new VehicleProducer();
System.out.println("Building Car:n");
CarBuilder carBuilder = new CarBuilder();
vehicleProducer.buildCar(carBuilder);
Car car = carBuilder.build();
System.out.println("nFinal result:n" + car);
System.out.println("----------------------------");
System.out.println("Building Car:n");
PlaneBuilder planeBuilder = new PlaneBuilder();
vehicleProducer.buildPlane(planeBuilder);
Plane plane = planeBuilder.build();
System.out.println("nFinal result:n" + plane);
}
}
Output
Output of the above demo code will be as below.
Building Car:
Add 4 wheels
Add 1 engine
Add 4 door
Add 4 Seat
Add interior
Final result:
Car: Wheel -> 4 | Engine -> 1 | Seat -> 4 | Door -> 4 | Interior -> true
----------------------------
Building Car:
Add 3 wheels
Add 2 engine
Add 4 door
Add 120 Seat
Add interior
Add 2 wing
Final result:
Plane: Wheel -> 3 | Engine -> 2 | Seat -> 120 | Door -> 4 | Wing: 0 | Interior -> true
Source Code
Use the following link to get the source code:
Other Code Implementations
Use the following links to check Builder pattern implementation in other programming languages.