Design Patterns : Builder Pattern
Points To Remember
- It is a Creational Design Pattern
- It must be used when you have multiple overloaded constructors or setters
- Its main purpose it to hide from the user, how the object is to be created.
- It is advised to make your constructors private when you are using Builder Design Pattern.
What is Builder Design Pattern
It is a creational design pattern. So it is only responsible for how an object must be created.
There may be scenarios where there is a class with many instance variables that may be needed to create an object of the class. For this you might have to create many overloaded constructors.
For Example we have a class NutritionFacts that has following instance variables
private int servingSize;
private int servings;
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
Then to create the object of the class we can have constructors as follows
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0);
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 35, 27);
As shown in the code above, it is not clear from the code itself what constructor is called for setting values.
This is the best example where we should use Builder Pattern for Building our class objects.
Now, when using Builder Pattern we will be able to tell from the code itself what values are we setting for which instance variable.
For example, if the above constructor were replaces by the following code sample.
NutritionFacts facts = new NutritionFacts.Builder(100,10)
.calories(785)
.carbohydrate(452)
.fat(24)
.sodium(8)
.build();
The above code is in itself readable and tells what values are we setting for variables.
Advantages of Builder Pattern
This makes the setting of variables and paramaters very readable and less error prone.
Disadvantages Of Builder Pattern
- If the number of paramaters are not more than 4 or the number of required paramaters are more than this may not be the optimal solution since the cost of making builders will be more.
- Another main disadvantage is that your builder should have same number of fields as the class itself, hence the duplicacy of code is more and you need to make changes to both class and Builder when adding or removing any field.
How to Implement Builder Design pattern in Java ?
To implement the Builder Design pattern in Java we will create a Builder Class for making object of our class.
-
We can have make this Builder class inside our class or even outside the class. How ever it is adviced to to create this class inside the class for which the object will be created. Otherwise you will not be able to make the constructor of the class private. If the construtor is not private then,the user can still make the object with the new keyword.
-
Also the Builder class should have all the field of the main class.
-
Builder class should be a static inner class of the Main class and set all the values to its instance variables instead of the Main class
-
The Builder class should have public setter methods and no getters.
-
When the build method is called it should build the object depending updon the values passed and return an object.
A sample class may look as follows
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
public int getServingSize() {
return servingSize;
}
public int getServings() {
return servings;
}
public int getCalories() {
return calories;
}
public int getFat() {
return fat;
}
public int getSodium() {
return sodium;
}
public int getCarbohydrate() {
return carbohydrate;
}
}
and now you can build the Object of the class NutritionFacts as follows
NutritionFacts facts = new NutritionFacts.Builder(100,10)
.calories(785)
.carbohydrate(452)
.fat(0)
.build();
No comments: