Java builder pattern example 2016-12-16 22:16
There are two kinds of builder pattern on the internet. Both of them separate the construction of a complex object from its representation. In this page I will show you how to use them.
1. The first kind (in the book Effective Java, 2nd Edition
)
This kind of builder pattern is easy. Car and CarBuilder code are like following.
public class Car {
private String name;
private int height;
private String color;
private int wheelNum;
static class CarBuilder {
private String name;
private int height;
private String color;
private int wheelNum;
public CarBuilder withName(String name) {
this.name = name;
return this;
}
public CarBuilder withHeight(int height) {
this.height = height;
return this;
}
public CarBuilder withColor(String color) {
this.color = color;
return this;
}
public CarBuilder withWheelNum(int wheelNum) {
this.wheelNum = wheelNum;
return this;
}
public Car build() {
return new Car(this);
}
}
private Car(CarBuilder carBuilder) {
this.name = carBuilder.name;
this.color = carBuilder.color;
this.height = carBuilder.height;
this.wheelNum = carBuilder.wheelNum;
}
@Override
public String toString() {
return "Vehicle{" +
"name='" + name + '\'' +
", height=" + height +
", color='" + color + '\'' +
", wheelNum=" + wheelNum +
'}';
}
// getter and setter methods
}
The code of client is like following. To build a Car
you need set the values into builder then invoke build
method of the builder.
public class Client {
public static void main(String[] args) {
Car car = new Car.CarBuilder()
.withName("Car")
.withHeight(1)
.withWheelNum(4)
.withColor("Red").build();
System.out.println(car);
}
}
2. The second kind (in wiki)
You need define a builder interface (CarBuilder) in this kind of Builder pattern. The concrete code of building a Car
is in the CarBuilderImpl
.
public class Car {
private String name;
private int height;
private String color;
private int wheelNum;
@Override
public String toString() {
return "Vehicle{" +
"name='" + name + '\'' +
", height=" + height +
", color='" + color + '\'' +
", wheelNum=" + wheelNum +
'}';
}
// getter and setter methods
}
public interface CarBuilder {
void setName(String name);
void setHeight(int height);
void setColor(String color);
void setWheelNum(int wheelNum);
Car createCar();
}
public class CarBuilderImpl implements CarBuilder {
Car car;
public CarBuilderImpl() {
this.car = new Car();
}
@Override
public void setName(String name) {
car.setName("Car");
}
@Override
public void setHeight(int height) {
car.setHeight(2);
}
@Override
public void setColor(String color) {
car.setColor("Red");
}
@Override
public void setWheelNum(int wheelNum) {
car.setWheelNum(4);
}
@Override
public Car createCar() {
return car;
}
}
You need a director to decide use which builder to build a car. You can implement CarBuilder
in different ways to build different kind of cars. The code of director is like following.
public class CarBuildDirector {
private CarBuilder builder;
public CarBuildDirector(CarBuilder builder) {
//you can pass different kind of builder to build different cars
this.builder = builder;
}
public Car construct() {
builder.setWheelNum(4);
builder.setColor("Red");
builder.setName("Car");
builder.setHeight(1);
return builder.createCar();
}
public static void main(String[] args) {
CarBuilder builder = new CarBuilderImpl();
CarBuildDirector carBuildDirector = new CarBuildDirector(builder);
System.out.println(carBuildDirector.construct());
}
}
Summary
Both of them are Builder pattern
. Using first kind of builder pattern can avoid multiple constructors. The second kind is flexible and safe. You have to implement every method in builder interface when add another kind of builder which make sure every properties be initialized.