The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations. - Gof
Builder pattern is used to construct a complex object step by step and the final step will return the object. The process of constructing an object should be generic so that it can be used to create different representations of the same object.With the builder pattern, the same object construction process can be used to create different objects.
https://en.wikipedia.org/wiki/Builder_pattern
Unlike the abstract factory pattern and the factory method patternwhose intention is to enable polymorphism, the intention of the builder pattern is to find a solution to the telescoping constructor anti-pattern
The telescoping constructor anti-pattern occurs when the increase of object constructor parameter combination leads to an exponential list of constructors. Instead of using numerous constructors, the builder pattern uses another object, a builder, that receives each initialization parameter step by step and then returns the resulting constructed object at once.
Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components are built. Builders are good candidates for a fluent interface.
The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.
https://dzone.com/articles/design-pattern-builder-pattern
A client object creates an instance of the Director object and passes it the appropriate Builder object. The Director object invokes the methods on the Builder object to create and initialize specific parts of the Product object. The Builder receives content from the Director object and adds these to the Product object. The Client object has a reference to the Builder object and retrieves the created Product object from it.
Difference between Builder and Factory
Builder pattern is used when there are many steps to create an object. Factory pattern is used when the factory can easily create the entire object within one method call.
In builder pattern emphasis is on ‘step by step’. Builder pattern will have many number of small steps. Those every steps will have small units of logic enclosed in it. There will also be a sequence involved. It will start from step 1 and will go on upto step n and the final step is returning the object. In these steps, every step will add some value in construction of the object. That is you can imagine that the object grows stage by stage. Builder will return the object in last step. But in abstract factory how complex the built object might be, it will not have step by step object construction.
How about template pattern?
Sample builder design pattern implementation in Java API
DocumentBuilderFactory , StringBuffer, StringBuilder are some examples of builder pattern usage in java API.
Does StringBuilder utilize the Builder pattern? -- No
Builder pattern is used when there are many steps to create an object. Factory pattern is used when the factory can easily create the entire object within one method call.
In builder pattern emphasis is on ‘step by step’. Builder pattern will have many number of small steps. Those every steps will have small units of logic enclosed in it. There will also be a sequence involved. It will start from step 1 and will go on upto step n and the final step is returning the object. In these steps, every step will add some value in construction of the object. That is you can imagine that the object grows stage by stage. Builder will return the object in last step. But in abstract factory how complex the built object might be, it will not have step by step object construction.
How about template pattern?
Sample builder design pattern implementation in Java API
DocumentBuilderFactory , StringBuffer, StringBuilder are some examples of builder pattern usage in java API.
Does StringBuilder utilize the Builder pattern? -- No
Example:
https://github.com/mission-peace/EffectiveJava/blob/master/src/com/ej/builder/Order.java
public class Order {
private final String orderId;
private final String customerId;
private final int orderPrice;
private final Date orderDate;
public static class Builder{
private String orderId;
private String customerId;
private int orderPrice;
private Date orderDate;
public Builder(String orderId, String customerId){
this.orderId = orderId;
this.customerId = customerId;
}
public Builder orderPrice(int orderPrice){
this.orderPrice = orderPrice;
return this;
}
public Builder orderDate(Date orderDate){
this.orderDate = orderDate;
return this;
}
public Order build(){
return new Order(orderId, customerId, orderPrice, orderDate);
}
}
private Order(String orderId, String customerId, int orderPrice, Date orderDate){
this.orderId = orderId;
this.customerId = customerId;
this.orderPrice = orderPrice;
this.orderDate = orderDate;
}
public static void main(String args[]){
Order.Builder builder = new Order.Builder("2131", "1515");
Order order = builder.orderPrice(10).orderDate(new Date()).build();
}
}
http://javapapers.com/design-patterns/builder-pattern/
he first issue has to do with having an instance of this class in an inconsistent state.
The second disadvantage of this approach is that now the User class is mutable. You’re loosing all the benefits of immutable objects.
public User getUser() {
return new
User.UserBuilder("Jhon", "Doe")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
}
The builder could even auto-complete some generated field between each invocation, such as an id or serial number.
An important point is that, like a constructor, a builder can impose invariants on its parameters. The build method can check these invariants and throw an IllegalStateExceptionif they are not valid.
It is critical that they be checked after copying the parameters from the builder to the object, and that they be checked on the object fields rather than the builder fields. The reason for this is that, since the builder is not thread-safe, if we check the parameters before actually creating the object their values can be changed by another thread between the time the parameters are checked and the time they are copied. This period of time is known as the “window of vulnerability”.
public User build() {
User user = new user(this);
if (user.getAge() > 120) {
throw new IllegalStateException(“Age out of range”); // thread-safe
}
return user;
}
// bad
public User build() {
if (age > 120) {
throw new IllegalStateException(“Age out of range”); // bad, not thread-safe
}
// This is the window of opportunity for a second thread to modify the value of age
return new User(this);
}
given the fact that the builder class is usually a static member class of the class it builds, they can evolve together fairly easy.
http://www.journaldev.com/1425/builder-design-pattern-in-java
large number of parameters by providing a constructor with required parameters and then different setter methods to set the optional parameters but the problem with this is that the Object state will be inconsistent until unless all the attributes are set explicitly.
Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.
Computer class has only getter methods and no public constructor, so the only way to get a Computer object is through the ComputerBuilder class.
public class Order {
private final String orderId;
private final String customerId;
private final int orderPrice;
private final Date orderDate;
public static class Builder{
private String orderId;
private String customerId;
private int orderPrice;
private Date orderDate;
public Builder(String orderId, String customerId){
this.orderId = orderId;
this.customerId = customerId;
}
public Builder orderPrice(int orderPrice){
this.orderPrice = orderPrice;
return this;
}
public Builder orderDate(Date orderDate){
this.orderDate = orderDate;
return this;
}
public Order build(){
return new Order(orderId, customerId, orderPrice, orderDate);
}
}
private Order(String orderId, String customerId, int orderPrice, Date orderDate){
this.orderId = orderId;
this.customerId = customerId;
this.orderPrice = orderPrice;
this.orderDate = orderDate;
}
public static void main(String args[]){
Order.Builder builder = new Order.Builder("2131", "1515");
Order order = builder.orderPrice(10).orderDate(new Date()).build();
}
}
HouseBuilder iglooBuilder = new IglooHouseBuilder(); CivilEngineer engineer = new CivilEngineer(iglooBuilder); engineer.constructHouse(); House house = engineer.getHouse();
public class CivilEngineer { private HouseBuilder houseBuilder; public CivilEngineer(HouseBuilder houseBuilder){ this.houseBuilder = houseBuilder; } public House getHouse() { return this.houseBuilder.getHouse(); } public void constructHouse() { this.houseBuilder.buildBasement(); this.houseBuilder.buildStructure(); this.houseBuilder.bulidRoof(); this.houseBuilder.buildInterior(); } }
public class TipiHouseBuilder implements HouseBuilder { private House house; //should use Interface HousePlan? public TipiHouseBuilder() { this.house = new House(); } public void buildBasement() { house.setBasement("Wooden Poles"); } public void buildStructure() { house.setStructure("Wood and Ice"); } public void buildInterior() { house.setInterior("Fire Wood"); } public void bulidRoof() { house.setRoof("Wood, caribou and seal skins"); } public House getHouse() { return this.house; } }
public class House implements HousePlan { private String basement; private String structure; private String roof; private String interior; public void setBasement(String basement) { this.basement = basement; } public void setStructure(String structure) { this.structure = structure; } public void setRoof(String roof) { this.roof = roof; } public void setInterior(String interior) { this.interior = interior; } }
X. Builder to replace complex constructor.
http://jlordiales.me/2012/12/13/the-builder-pattern-in-practice/he first issue has to do with having an instance of this class in an inconsistent state.
The second disadvantage of this approach is that now the User class is mutable. You’re loosing all the benefits of immutable objects.
public User getUser() {
return new
User.UserBuilder("Jhon", "Doe")
.age(30)
.phone("1234567")
.address("Fake address 1234")
.build();
}
- The User constructor is private, which means that this class can not be directly instantiated from the client code.
- The class is once again immutable. All attributes are final and they’re set on the constructor. Additionally, we only provide getters for them.
- The builder uses the Fluent Interface idiom to make the client code more readable (we’ll see an example of this in a moment).
- The builder constructor only receives the required attributes and this attributes are the only ones that are defined “final” on the builder to ensure that their values are set on the constructor.
The builder could even auto-complete some generated field between each invocation, such as an id or serial number.
An important point is that, like a constructor, a builder can impose invariants on its parameters. The build method can check these invariants and throw an IllegalStateExceptionif they are not valid.
It is critical that they be checked after copying the parameters from the builder to the object, and that they be checked on the object fields rather than the builder fields. The reason for this is that, since the builder is not thread-safe, if we check the parameters before actually creating the object their values can be changed by another thread between the time the parameters are checked and the time they are copied. This period of time is known as the “window of vulnerability”.
public User build() {
User user = new user(this);
if (user.getAge() > 120) {
throw new IllegalStateException(“Age out of range”); // thread-safe
}
return user;
}
// bad
public User build() {
if (age > 120) {
throw new IllegalStateException(“Age out of range”); // bad, not thread-safe
}
// This is the window of opportunity for a second thread to modify the value of age
return new User(this);
}
given the fact that the builder class is usually a static member class of the class it builds, they can evolve together fairly easy.
http://www.journaldev.com/1425/builder-design-pattern-in-java
large number of parameters by providing a constructor with required parameters and then different setter methods to set the optional parameters but the problem with this is that the Object state will be inconsistent until unless all the attributes are set explicitly.
Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.
Computer class has only getter methods and no public constructor, so the only way to get a Computer object is through the ComputerBuilder class.
public
class
Computer
//required parameters
private
String HDD;
private
String RAM;
//optional parameters
private
boolean
isGraphicsCardEnabled;
private
boolean
isBluetoothEnabled;
public
String getHDD()
public
String getRAM()
public
boolean
isGraphicsCardEnabled()
public
boolean
isBluetoothEnabled()
private
Computer(ComputerBuilder builder) {
this
.HDD=builder.HDD;
this
.RAM=builder.RAM;
this
.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
this
.isBluetoothEnabled=builder.isBluetoothEnabled;
}
//Builder Class
public
static
class
ComputerBuilder{
// required parameters
private
String HDD;
private
String RAM;
// optional parameters
private
boolean
isGraphicsCardEnabled;
private
boolean
isBluetoothEnabled;
public
ComputerBuilder(String hdd, String ram){
this
.HDD=hdd;
this
.RAM=ram;
}
public
ComputerBuilder setGraphicsCardEnabled(
boolean
isGraphicsCardEnabled) {
this
.isGraphicsCardEnabled = isGraphicsCardEnabled;
return
this
;
}
public
ComputerBuilder setBluetoothEnabled(
boolean
isBluetoothEnabled) {
this
.isBluetoothEnabled = isBluetoothEnabled;
return
this
;
}
public
Computer build(){
return
new
Computer(
this
);
}
}
}
Computer comp =
new
Computer.ComputerBuilder(
"500 GB"
,
"2 GB"
).setBluetoothEnabled(
true
)
.setGraphicsCardEnabled(
true
).build();
MealBuilder
ItalianMealBuilder
Product: Meal
MealDirector
http://www.codeproject.com/Articles/42415/Builder-Design-Pattern
Kid build Animal.
http://javarevisited.blogspot.com/2012/06/builder-design-pattern-in-java-example.html
Advantages:
1) more maintainable if number of fields required to create object is more than 4 or 5.
2) less error-prone as user will know what they are passing because of explicit method call.
3) more robust as only fully constructed object will be available to client.
Disadvantages:
1) verbose and code duplication as Builder needs to copy all fields from Original or Item class.
UPDATE: if you use Eclipse as your IDE, it turns out that you have quite a few plugins to avoid most of the boiler plate code that comes with the pattern. The three I’ve seen are:
Too Many Parameters in Java Methods, Part 3: Builder Pattern
http://www.javaworld.com/article/2074938/core-java/too-many-parameters-in-java-methods-part-3-builder-pattern.html
http://www.oodesign.com/builder-pattern.html