Friday, 16 January 2015

Understanding Builder Design Pattern

Before starting with Builder Design pattern concept and how we can implement this in java, let me first take you to issues which we face in our code practice.

This would help us to connect better with learning of Builder Design pattern.

Take an example of alloy composition(e.g. stainless steel). Alloy composition is built on a number of organic complex elements in predefined percentage(by mass).

So quality of an alloy depends on percentage of building elements added during process. We can take example of Ashok Stambh, New Delhi which was built during 3rd Century BC and still no sign of rust on it :-)

Now if we have to write down "Alloy" class in java that would be something like below:

 public class Alloy{  
      private float iron;  
      private float chromium;  
      private float molybdenum;  
      private float carbon;  
     public Alloy() {  
           super();  
      }  
      public Alloy(float iron, float chromium, float molybdenum, float carbon) {  
           super();  
           this.iron = iron;  
           this.chromium = chromium;  
           this.molybdenum = molybdenum;  
           this.carbon = carbon;  
      }  
      public float getIron() {  
           return iron;  
      }  
      public void setIron(float iron) {  
           this.iron = iron;  
      }  
      public float getChromium() {  
           return chromium;  
      }  
      public void setChromium(float chromium) {  
           this.chromium = chromium;  
      }  
      public float getMolybdenum() {  
           return molybdenum;  
      }  
      public void setMolybdenum(float molybdenum) {  
           this.molybdenum = molybdenum;  
      }  
      public float getCarbon() {  
           return carbon;  
      }  
      public void setCarbon(float carbon) {  
           this.carbon = carbon;  
      }  
 }  


Say our client code want to create an instance of Alloy class so there can be 2 ways to do:

1. call default constructor of Alloy class and then set all instance variables by setter of Alloy class.
2. Other way can be call parameterized constructor, pass all user inputs in one go and create instance of Alloy class.

Here we have only 4 instance variable in Alloy class, but suppose if a class has more than 10 instance variables.

In that case calling setter for all instance variables in client code will be not look good as it increases line of code. At the same time calling parameterzied constructor with all 10 inputs will lead to programming error, where programmer passed wrong values in constructor.

Here Builder Design pattern comes into picture to rescue us.

Let us modify the existing Alloy class and see how builder pattern overcome with above mentioned 2 issues.

 public class Alloy {  
      private float iron;  
      private float chromium;  
      private float molybdenum;  
      private float carbon;  
      private Alloy(Builder builder){  
           this.iron = builder.iron;  
           this.chromium = builder.chromium;  
           this.molybdenum = builder.molybdenum;  
           this.carbon = builder.carbon;  
      }  
      public static class Builder{  
           private float iron;  
           private float chromium;  
           private float molybdenum;  
           private float carbon;  
           public Builder(){  
                super();  
           }  
           public Builder iron(int val){  
                iron = val;  
                return this;  
           }  
           public Builder chromium(int val){  
                chromium = val;  
                return this;  
           }  
           public Builder molybdenum(int val){  
                molybdenum = val;  
                return this;  
           }  
           public Builder carbon(int val){  
                carbon = val;  
                return this;  
           }  
           public Alloy build(){  
                return new Alloy(this);  
           }  
      }  
 }  

Here our intention it to first create basic object and build required object on top of that. So we introduced an inner class say Builder which will take the responsibility of building object of Alloy class.


Let see how code looks like in client end who wants to create instance of  Alloy class

 Alloy stainlessSteel = new Alloy.Builder().iron(30).chromium(12)  
                                                   .molybdenum(20).carbon(40).build();  

As you can see, how we are creating an instance of Alloy class in a meaningful way that too with less line of codes. There is no whole bunch of setters or passing a number of parameters in parameterized constructor.

At last formal definition of "Builder Design Pattern" (wiki):
Builder Design 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.

Suggestions: I would suggest book "Effective Java 2" by Joshua Bloach who explained Builder Design Pattern in simple but effective way.

No comments:

Post a Comment