The builder pattern is an alternative way to construct complex objects. This should be used only when you want to build different immutable objects using same object building process. Builder pattern aims to Separate the construction of a complex object from its representation so that the same construction process can create different representations.
Why do we need Builder Pattern:
We all know that constructors in java are used to create objects and takes the parameters that are required create them. The problem starts when we have lot of parameters and some of them may be mandatory and some are optional.
To illustrate the problem, lets take an example of ordering ice cream online. There are multiple varieties of the ice creams available currently in the market.Each person has different choices of toppings, flavors etc. Now consider that you are creating an object for each user's choice. In this case you will end up creating multiple constructors based each user's choice. Also, if you pass the value of one parameter to other parameter, the whole thing would mess up.
Problems:
1. Too many constructors
2. Error prone because of multiple parameters
3. The order has to be followed while creating the object.
Builder pattern solves all the above problems. Lets see an implementation example.
============================================================
public class BuilderPatternValidator {
public static void main(String args[]) {
// Creating object using Builder pattern in java
IceCream MilkIceCream = new IceCream.Builder().milk(1).chocochips(2).caramel(2).dryfuits(1.5).m_ms(0.75).build();
IceCream SoyaIceCream = new IceCream.Builder().soya(1).peanuts(2).caramel(2).dryfuits(1.5).m_ms(0.75).build();
// IceCream is ready to eat :)
System.out.println(MilkIceCream);
System.out.println(SoyaIceCream);
}
}
class IceCream {
private final double milk; // cup
private final double soya; // cup
private final int chocochips; // spoon
private final int caramel; // spoon
private final double peanuts; // cup
private final double dryfuits; // spoon
private final double m_ms; // cup
private final int cherry; // number
public static class Builder {
private double milk; // cup
private double soya; // cup
private int chocochips; // spoon
private int caramel; // spoon
private double peanuts; // spoon
private double dryfuits; // spoon
private double m_ms; // cup
private int cherry; // number
// builder methods for setting property
public Builder milk(double cup) {
this.milk = cup;
return this;
}
public Builder soya(double cup) {
this.soya = cup;
return this;
}
public Builder chocochips(int spoon) {
this.chocochips = spoon;
return this;
}
public Builder caramel(int spoon) {
this.caramel = spoon;
return this;
}
public Builder peanuts(int spoon) {
this.peanuts = spoon;
return this;
}
public Builder dryfuits(double spoon) {
this.dryfuits = spoon;
return this;
}
public Builder m_ms(double spoon) {
this.m_ms = spoon;
return this;
}
public Builder cherry(int number) {
this.cherry = number;
return this;
}
// return fully build object
public IceCream build() {
return new IceCream(this);
}
}
// private constructor to enforce object creation through builder
private IceCream(Builder builder) {
this.milk = builder.milk;
this.soya = builder.soya;
this.chocochips = builder.chocochips;
this.caramel = builder.caramel;
this.peanuts = builder.peanuts;
this.dryfuits = builder.dryfuits;
this.m_ms = builder.m_ms;
this.cherry = builder.cherry;
}
@Override
public String toString() {
return "IceCream { " + "milk=" + milk + ", soya=" + soya + ", chocochips=" + chocochips + ", caramel="
+ caramel + ", peanuts=" + peanuts + ", dryfuits=" + dryfuits + ", m_ms=" + m_ms
+ ", cherry=" + cherry + '}';
}
}
=========================================================
Points to be noted from the above example are:
- IceCream constructor is private, which means that this class can not be directly instantiated from the client code.
- While creating the objects, I have declared only the parameters that are needed
- The order of the parameters can be varied.
- Code looks more readable.
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 IceCream class.
How to use this builder pattern in Automation:
The builder pattern is very handy particularly in API automation, where we deal with large number of parameters. While creating the requests, we use pojo classes. This builder pattern can be used to construct the object with the required parameters and pass it to pojo classes. This way we can reduce lot of code duplication.
No comments:
Post a Comment