33
loading...
This website collects cookies to deliver better user experience
“Builder pattern is more verbose than the telescoping constructor pattern, so it should be used only if there are enough parameters, say, four or more.” ― Joshua Bloch, Effective Java
HouseWithGarageAndSwimmingPool
class House {
constructor(hasSwimmingPool, hasGarage, hasGarden){
// some stuff
}
}
HouseBuilder
.interface Builder {
public void buildWalls()
public void buildDoors()
public void buildWindows()
public void buildRoof()
public void buildGarage()
public void buildGarden()
public void buildSwimmingPool()
}
class HouseBuilder implements Builder {
public void buildWalls() {
// build walls
}
public void buildDoors() {
// build doors
}
public void buildWindows() {
// build windows
}
public void buildRoof() {
// build roof
}
public void buildGarage() {
// build garage
}
public void buildGarden() {
// build garden
}
public void buildSwimmingPool(){
// build swimming pool
}
public House getResult(){
// return the fully configured house
}
}
HouseStoneBuilder
and HouseClayBuilder
. Plus, because we are using the same interface for each builder, the client code can easily swap between builders.public House buildHouse(type){
builder = new HouseBuilder()
// build what's common in all houses
builder.buildWalls()
builder.buildDoors()
builder.buildWindows()
builder.buildRoof()
if(type === "withGarage"){
builder.buildGarage()
}
if(type === "withGarden"){
builder.buildGarden()
}
if(type == "withSwimmingPool"){
builder.buildSwimmingPool()
}
House house = builder.getResult()
return house
}
Director
. Director
class is like an engineer, it knows the steps in creating the houses, and uses implementations of the builders to create them.class Director extends {
Builder builder;
constructor(Builder builder){
this.builder = builder;
}
buildHouse(){
this.builder.buildWalls()
this.builder.buildDoors()
this.builder.buildWindows()
this.builder.buildRoof()
return this.builder.getResult()
}
buildHouseWithSwimmingPool(){
this.builder.buildWalls()
this.builder.buildDoors()
this.builder.buildWindows()
this.builder.buildRoof()
this.builder.buildSwimmingPool()
return this.builder.getResult()
}
// other configurations
}
Director
class is ready, we can refactor our original client code:public House buildHouse(type){
builder = new HouseBuilder()
director = new Director(builder)
House house = director.buildHouse()
// you can add if statements for other configs
if(type === "withGarage"){
house = director.buildHouseWithGarage()
}
return house
}
Use the Builder pattern to get rid of huge constructors.
As we have seen in our first example, object creation can be a complex thing. So if you see that you have a huge constructor that takes way too many parameters and is simply complex and hard to maintain. This may be an opportunity to refactor it to the Build pattern.
Use the Builder pattern when you want to create different variations of objects.
The Builder pattern allows us to destruct object creation into a step by step process, where you the developer can control each step. This allows us to create different variations of objects using different builder classes and directors.
Use the Builder pattern to construct complex objects such as Composite Trees.
As stated above, we control the whole process in object creation, we can even recursively create objects to construct composite trees or other complex objects.