Code Pumpkin

Builder Design Pattern

April 27, 2017
Posted by Pumpkin
Subscribe

Builder design pattern is a creational design pattern like Factory Pattern and Abstract Factory Pattern.

For better understanding of  any design pattern, You should know the problems faced by programmers before that design pattern was introduced.

What are the traditional ways of creating an object of a class?

We can provide either constructor or a static factory method to get the object  of our class. But providing a constructor and static factory method for large number of parameters in not a good practice.

For Example, 

Lets take an example of online movie ticket booking portal, where all the users can book the movie tickets. Additionally they can also include beverages in their bookings.

For the sake of brevity, we will assume that portal is providing option for only 4 beverages i.e. Popcorn, Pizza, Burger and Coke.

We will create class with fields movie, totalTickets, popcorn, pizza, burger and coke.

Traditional way of creating objects: 

  1. Telescoping Constructor Pattern or Telescoping Static Factories
  2.  JavaBeans Pattern

Telescoping Constructor Pattern

In this pattern, you 

What sort of constructor or static factories should you write for this class? Traditionally, programmers uses the telescoping constructor pattern, in which you provide a constructor with only the required parameters, another with a single optional parameter, a third with two optional parameters, and so on, culminating in a constructor with all the optional parameters. Here’s how it looks in practice. 


public class MovieTicketBooking {

	
	private final String movie;    // Name of the Movie
	private final int totalTickets; // Total tickets booked
	private final int popcorn;      // quantity of popcorn
	private final int pizza;        // quantity of Pizza
	private final int burger;       // quantity of burger
	private final int coke;         // quantity of coke
	
		
	public MovieTicketBooking(String movie, int totalTickets) {
		this(movie, totalTickets, 0);
	}
	
	public MovieTicketBooking(String movie, int totalTickets, int popcorn) {
		this(movie, totalTickets, popcorn, 0);
	}
	
	public MovieTicketBooking(String movie, int totalTickets, int popcorn, int pizza) {
		this(movie, totalTickets, popcorn, pizza, 0);
	}
	
	public MovieTicketBooking(String movie, int totalTickets, int popcorn, int pizza, int burger) {
		this(movie, totalTickets, popcorn, pizza, burger, 0);
	}

	public MovieTicketBooking(String movie, int totalTickets, int popcorn, int pizza, int burger, int coke) {
		this.movie = movie;
		this.totalTickets = totalTickets;
		this.popcorn = popcorn;
		this.pizza = pizza;
		this.burger = burger;
		this.coke = coke;
	}
	
	
}

When you want to create an instance, you use the constructor with the shortest parameter list containing all the parameters you want to set. 


MovieTicketBooking movieTest = 
                new MovieTicketBooking("3 Idiots", 5, 2, 0, 3, 5);

Disadvantages

  1. Typically this constructor invocation will require many parameters that you don’t want to set, but you’re forced to pass a value for them anyway. In this case, even if I don't want to order Pizza, I need to include it with value 0 as I want burger and coke to be included in my order.
  2. With “only” six parameters this may not seem so bad, but it quickly gets out of hand as the number of parameters increases. Also adding one new filed to the class will require to writeentire new constructor.
  3. Writing and reading a code with telescoping constructor pattern needs lots of attention. The reader is left wondering what all those values mean and must carefully count parameters to find out. Long sequences of identically typed parameters can cause subtle bugs. If the client accidentally reverses two such parameters, the compiler won’t complain, but the program will misbehave at runtime.

JavaBeans pattern

A second alternative when you are faced with many constructor parameters is the JavaBeans pattern, in which you call a parameterless constructor to create the object and then call setter methods to set each required parameter and each optional parameter of interest:


public class MovieTicketBooking {

	
	private String movie;    // Name of the Movie
	private int totalTickets; // Total tickets booked
	private int popcorn;      // quantity of popcorn
	private int pizza;        // quantity of Pizza
	private int burger;       // quantity of burger
	private int coke;         // quantity of coke
	
	public MovieTicketBooking() { }

	public void setMovie(String movie) {
		this.movie = movie;
	}

	public void setTotalTickets(int totalTickets) {
		this.totalTickets = totalTickets;
	}

	public void setPopcorn(int popcorn) {
		this.popcorn = popcorn;
	}

	public void setPizza(int pizza) {
		this.pizza = pizza;
	}

	public void setBurger(int burger) {
		this.burger = burger;
	}

	public void setCoke(int coke) {
		this.coke = coke;
	}
}

It is easy to create instances, and easy to read the resulting code:


MovieTicketBooking movieTest = new MovieTicketBooking ();
movieTest.setMovie("3 Idiots");
movieTest.setTotalTickets(5);
movieTest.setPopcorn(2);
movieTest.setBurger(3);
movieTest.setCoke(5);

Here you do not need to set value of Pizza as you do not want to order them.

Disadvantages

This pattern has none of the disadvantages of the telescoping constructor pattern.  Unfortunately, the JavaBeans pattern has serious disadvantages of its own.

  1. Because construction is split across multiple calls, this approach has the disadvantage of objects leaving in an inconsistent state  and you have to put in extra effort to ensure thread safety.
  2. JavaBeans pattern also precludes the possibility of making a class immutable.

Builder Design Pattern

To overcome all the disadvantages of above two patterns, Builder Design Pattern was introduced.

According to GOF:

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.

The builder design pattern provides a way to build complex immutable objects. Steps to implement Builder Design Pattern:

For better understanding, please check below code snippet while reading this steps:

  1. Make all fields private final 
  2. Create inner class Builder which is having same number of private fields as in outer class. (Inner class fields are not required to have the same name as outer class, but it is good practice to keep them same as outer class)
  3. In Builder class, create one constructor for all the required fields and create setter methods for optional fields.
  4. All this setter methods should return Builder class object to achieve method chaining. (Check client code for method chaining) 
  5. Create copy constructor in outer class which uses Builder object fields.

public class MovieTicketBooking {

	
	private final String movie;     // Name of the Movie
	private final int totalTickets; // Total tickets booked
	private final int popcorn;      // quantity of popcorn
	private final int pizza;        // quantity of Pizza
	private final int burger;       // quantity of burger
	private final int coke;         // quantity of coke
	
	private MovieTicketBooking(Builder builder)
	{
		movie = builder.movie;
		totalTickets = builder.totalTickets;
		popcorn = builder.popcorn;
		pizza = builder.pizza;
		burger = builder.burger;
		coke = builder.coke;
	}
	
	public static class Builder{
		private final String movie;     
		private final int totalTickets; 
		private int popcorn;      
		private int pizza;        
		private int burger;       
		private int coke;
		
		public Builder(String movie, int totalTickets) {
			this.movie = movie;
			this.totalTickets = totalTickets;
		}
		
		public Builder popcorn(int val){
			popcorn = val;
			return this;
		}
		
		public Builder pizza(int val){
			pizza = val;
			return this;
		}
		
		public Builder burger(int val){
			burger = val;
			return this;
		}
		
		public Builder coke(int val){
			coke = val;
			return this;
		}
		
		public MovieTicketBooking build()
		{
			return new MovieTicketBooking(this);
		}
	}
		
}

The process to write client code:

  1. The client calls a constructor with all the required fields and gets a Builder object. Here builder is a static member class of the class it builds.
  2. The client calls setter like methods to set each optional parameter of interest. The Builder's setter methods return the Builder itself so that invocations can be chained. 
  3. Finally the client calls the build method to generate the new object which is immutable.

For Example,


MovieTicketBooking movieTest = MovieTicketBooking.Builder("3 Idiots", 5)
                                 .popcorn(2)
                                 .burger(3)
                                 .coke(5)
                                 .build();

Advantages

  1. A minor advantage of builders over constructors is that builders can have multiple varargs parameters. Constructors, like methods, can have only one varargs parameter. Because builders use separate methods to set each parameter, they can have as many varargs parameters as you like, up to one per setter method.
  2. The Builder pattern is flexible. A single builder can be used to build multiple objects. The parameters of the builder can be tweaked between object creations to vary the objects. for example, 

MovieTicketBooking.Builder movieBuilder = 
                                MovieTicketBooking.Builder("3 Idiots", 5);

MovieTicketBooking movieTest1 = movieBuilder.popcorn(2).build();
MovieTicketBooking movieTest2 = movieBuilder.coke(5).build();
  1. Builder design pattern is used to build immutable objects without much complex logic in object building process. To know more about creating immutable objects, read our post How To Create Immutable Class In Java

Disadvantage

  1. In order to create an object, you must first create its builder. While the cost of creating the builder is unlikely to be noticeable in practice, it could be a problem in some performance critical situations. 
  2. Also, the Builder pattern is more verbose than the telescoping constructor pattern, so it should be used only if there are enough parameters, say, four or more.

In summary, the Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if most of those parameters are optional.

Client code is much easier to read and write with builders than with the traditional telescoping constructor pattern, and builders are much safer than JavaBeans.

Existing implementations in JDK

All implementations of java.lang.Appendable are in fact good example of use of Builder pattern in java. e.g.

  1. java.lang.StringBuilder#append() [Unsynchronized class]
  2. java.lang.StringBuffer#append() [Synchronized class]
  3. java.nio.ByteBuffer#put() (also on CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer and DoubleBuffer)

Tags: , , ,


Comments and Queries

If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code class="java"> 
String foo = "bar";
</code></pre>
For more information on supported HTML tags in disqus comment, click here.

Total Post : 80
Subscribe
Contribute Your Articles

Interview Experiences

Related Books

Like Us On Facebook

Alexa Page Rank