Introduction
We will split our discussion into three sections - where to use this design pattern, how to use this design pattern and what is this design pattern. I will discuss what is builder design pattern at the end because the definition of any design pattern will not make sense until you know how and where to use it. In order to discuss where to use builder design pattern, we need to start with the problem statement.
private String firstName; //required
private String lastName; //required
private String phone; //optional
private String shippingAddress; //optional
private String billingAddress; //optional
Problem Statement (Where to use builder design pattern):
Create a class to store the following details of a customer in the database:private String firstName; //required
private String lastName; //required
private String phone; //optional
private String shippingAddress; //optional
private String billingAddress; //optional
The user class will have 4 different types of constructors based on the number of arguments being passed. The limitation of this design is that if a client reverses the two parameters while passing. The compiler won't complain but the code will break at the runtime. So, a client has to take care of the order of the arguments being passed in the constructor. This problem can be solved by using builder design pattern where a User class will be accessed indirectly by using an instance of UserBuilder class.public class User { private String firstName; //required private String lastName; //required private String phone; //optional private String shippingAddress; //optional private String billingAddress; //optional public User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public User(String firstName, String lastName, String phone) { this.firstName = firstName; this.lastName = lastName; this.phone = phone; } public User(String firstName, String lastName, String phone, String shippingAddress) { this.firstName = firstName; this.lastName = lastName; this.phone = phone; this.shippingAddress = shippingAddress; } public User(String firstName, String lastName, String phone, String shippingAddress, String billingAddress) { this.firstName = firstName; this.lastName = lastName; this.phone = phone; this.shippingAddress = shippingAddress; this.billingAddress = billingAddress; } }
How to use Builder design pattern:
public class User { private final String firstName; // required private final String lastName; // required private final String phone; // optional private final String shippingAddress; // optional private final String billingAddress; // optionalprivate User(UserBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.phone = builder.phone; this.shippingAddress = builder.shippingAddress; this.billingAddress = builder.billingAddress; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getPhone() { return phone; } public String getShippingAddress() { return shippingAddress; } public String getBillingAddress() { return billingAddress; } public class UserBuilder { private final String firstName; private final String lastName; private String phone; private String shippingAddress; private String billingAddress; public UserBuilder(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public UserBuilder phone(String phone) { this.phone = phone; return this; } public UserBuilder shippingAddress(String shippingAddress) { this.shippingAddress = shippingAddress; return this; } public UserBuilder billingAddress(String billingAddress) { this.billingAddress = billingAddress; return this; } private User build() { return new User(this); } } }
The advantages of this approach are:
- The User constructor is private, which means that this class cannot be directly instantiated from the client code.
- The client code is easier to write because doesn't need to worry about the order of the arguments in the constructor.
- The class is once again immutable. All attributes are final and they’re set on the constructor. Additionally, we only provide getters for them.
Comments
Post a Comment