Core Java

The builder pattern in practice

I’m not going to dive into much details about the pattern because there’s already tons of posts and books that explain it in fine detail. Instead, I’m going to tell you why and when you should consider using it. However, it is worth mentioning that this pattern is a bit different to the one presented in the Gang of Four book. While the original pattern focuses on abstracting the steps of construction so that by varying the builder implementation used we can get a different result, the pattern explained in this post deals with removing the unnecessary complexity that stems from multiple constructors, multiple optional parameters and overuse of setters.

Imagine you have a class with a substantial amount of attributes like the User class below. Let’s assume that you want to make the class immutable (which, by the way,
 
unless there’s a really good reason not to you should always strive to do. But we’ll get to that in a different post).

public class User {
    private final String firstName;    //required
    private final String lastName;    //required
    private final int age;    //optional
    private final String phone;    //optional
    private final String address;    //optional
...
}

Now, imagine that some of the attributes in your class are required while others are optional. How would you go about building an object of this class? All attributes are declared final so you have to set them all in the constructor, but you also want to give the clients of this class the chance of ignoring the optional attributes.

A first and valid option would be to have a constructor that only takes the required attributes as parameters, one that takes all the required attributes plus the first optional one, another one that takes two optional attributes and so on. What does that look like? Something like this:

    public User(String firstName, String lastName) {
        this(firstName, lastName, 0);
    }

    public User(String firstName, String lastName, int age) {
        this(firstName, lastName, age, '');
    }

    public User(String firstName, String lastName, int age, String phone) {
        this(firstName, lastName, age, phone, '');
    }

    public User(String firstName, String lastName, int age, String phone, String address) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.phone = phone;
        this.address = address;
    }

The good thing about this way of building objects of the class is that it works. However, the problem with this approach should be pretty obvious. When you only have a couple of attributes is not such a big deal, but as that number increases the code becomes harder to read and maintain. More importantly, the code becomes increasingly harder for clients. Which constructor should I invoke as a client? The one with 2 parameters? The one with 3? What is the default value for those parameters where I don’t pass an explicit value? What if I want to set a value for address but not for age and phone? In that case I would have to call the constructor that takes all the parameters and pass default values for those that I don’t care about. Additionally, several parameters with the same type can be confusing. Was the first String the phone number or the address?

So what other choice do we have for these cases? We can always follow the JavaBeans convention, where we have a default no-arg constructor and have setters and getters for every attribute. Something like:

public class User {
	private String firstName; // required
	private String lastName; // required
	private int age; // optional
	private String phone; // optional
	private String address;  //optional

	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

This approach seems easier to read and maintain. As a client I can just create an empty object and then set only the attributes that I’m interested in. So what’s wrong with it? There are two main problems with this solution. The first issue has to do with having an instance of this class in an inconsistent state. If you want to create an User object with values for all its 5 attributes then the object will not have a complete state until all the setX methods have been invoked. This means that some part of the client application might see this object and assume that is already constructed while that’s actually not the case. The second disadvantage of this approach is that now the User class is mutable. You’re loosing all the benefits of immutable objects.

Fortunately there is a third choice for these cases, the builder pattern. The solution will look something like the following.

public class User {
	private final String firstName; // required
	private final String lastName; // required
	private final int age; // optional
	private final String phone; // optional
	private final String address; // optional

	private User(UserBuilder builder) {
		this.firstName = builder.firstName;
		this.lastName = builder.lastName;
		this.age = builder.age;
		this.phone = builder.phone;
		this.address = builder.address;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	public String getPhone() {
		return phone;
	}

	public String getAddress() {
		return address;
	}

	public static class UserBuilder {
		private final String firstName;
		private final String lastName;
		private int age;
		private String phone;
		private String address;

		public UserBuilder(String firstName, String lastName) {
			this.firstName = firstName;
			this.lastName = lastName;
		}

		public UserBuilder age(int age) {
			this.age = age;
			return this;
		}

		public UserBuilder phone(String phone) {
			this.phone = phone;
			return this;
		}

		public UserBuilder address(String address) {
			this.address = address;
			return this;
		}

		public User build() {
			return new User(this);
		}

	}
}

A couple of important points worth noting:

  • The User constructor is private, which means that this class can not be directly instantiated from the client code.
  • The class is once again immutable. All attributes are final and they’re set on the constructor. Additionally, we only provide getters for them.
  • The builder uses the Fluent Interface idiom to make the client code more readable (we’ll see an example of this in a moment).
  • The builder constructor only receives the required attributes and this attributes are the only ones that are defined “final” on the builder to ensure that their values are set on the constructor.

The use of the builder pattern has all the advantages of the first two approaches I mentioned at the beginning and none of their shortcomings. The client code is easier to write and, more importantly, to read. The only critique that I’ve heard about the pattern is the fact that you have to duplicate the class’ attributes on the builder. However, given the fact that the builder class is usually a static member class of the class it builds, they can evolve together fairly easy.

Now, how does the client code trying to create a new User object looks like? Let’s see:

	public User getUser() {
		return new
				User.UserBuilder('Jhon', 'Doe')
				.age(30)
				.phone('1234567')
				.address('Fake address 1234')
				.build();
	}

Pretty neat, isn’t it? You can build a User object in 1 line of code and, most importantly, is very easy to read. Moreover, you’re making sure that whenever you get an object of this class is not going to be on an incomplete state.

This pattern is really flexible. A single builder can be used to create multiple objects by varying the builder attributes between calls to the “build” method. The builder could even auto-complete some generated field between each invocation, such as an id or serial number.

An important point is that, like a constructor, a builder can impose invariants on its parameters. The build method can check these invariants and throw an IllegalStateException if they are not valid.
It is critical that they be checked after copying the parameters from the builder to the object, and that they be checked on the object fields rather than the builder fields. The reason for this is that, since the builder is not thread-safe, if we check the parameters before actually creating the object their values can be changed by another thread between the time the parameters are checked and the time they are copied. This period of time is known as the “window of vulnerability”. In our User example this could look like the following:

public User build() {
    User user = new user(this);
    if (user.getAge() 120) {
        throw new IllegalStateException(“Age out of range”); // thread-safe
    }
    return user;
}

The previous version is thread-safe because we first create the user and then we check the invariants on the immutable object. The following code looks functionally identical but it’s not thread-safe and you should avoid doing things like this:

public User build() {
    if (age 120) {
        throw new IllegalStateException(“Age out of range”); // bad, not thread-safe
    }
    // This is the window of opportunity for a second thread to modify the value of age
    return new User(this);
}

A final advantage of this pattern is that a builder could be passed to a method to enable this method to create one or more objects for the client, without the method needing to know any kind of details about how the objects are created. In order to do this you would usually have a simple interface like:

public interface Builder {
    T build();
}

In the previous User example, the UserBuilder class could implement Builder<User>. Then, we could have something like:

UserCollection buildUserCollection(Builder<? extends User> userBuilder){...}

Well, that was a pretty long first post. To sum it up, the Builder pattern is an excellent choice for classes with more than a few parameters (is not an exact science but I usually take 4 attributes to be a good indicator for using the pattern), especially if most of those parameters are optional. You get client code that is easier to read, write and maintain. Additionally, your classes can remain immutable which makes your code safer.

UPDATE: if you use Eclipse as your IDE, it turns out that you have quite a few plugins to avoid most of the boiler plate code that comes with the pattern. The three I’ve seen are:

I haven’t tried any of them personally so I can’t really give an informed decision on which one is better. I reckon that similar plugins should exist for other IDEs.
 

Reference: The builder pattern in practice from our JCG partner Jose Luis at the Development the way it should be blog.

Jose Luis

Jose Luis is a computer scientist and professional senior software engineer with experience in a wide variety of technologies, particularly those oriented towards the JVM platform. He is mainly interested in back-end development and Agile practices that make software development both more fun and more valuable to customers.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

38 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Marco Castigliego
Marco Castigliego
11 years ago

Nice article! I like the builder pattern,but I think it lacks of some control. I wrote a post in my blog few months ago explaining an enhanced version of this pattern called step builder : http://rdafbn.blogspot.ie/2012/07/step-builder-pattern_28.html . If you have time I’d like to know what you think about it.

Joel Dean
10 years ago

Great post Jose!

Fabián López
Fabián López
10 years ago

This actually makes sense, i never really understood the “clasical” builder pattern. Thanks

chandra
chandra
10 years ago

excellent

Abhinav
Abhinav
10 years ago

Awesome explanation !!!

I actually helped me in understanding how alert dialog builder actually works in Android

chandra
chandra
10 years ago

Excellent explanation……….

Mathias Bogaert
Mathias Bogaert
10 years ago

For Intellij IDEA, see this plugin: http://plugins.jetbrains.com/plugin/7354

Gajendra Choudhary
10 years ago

Very nice article, with this i understood what builder pattern is all about, thanks again for sharing your knowledge.

Cene Lavrič
Cene Lavrič
9 years ago

Nice explanation of the concept. Although I could not grasp entirely the idea of buildUserCollection. What I miss in builder pattern is support for inheritance: Say class A comprising a mandatory attribute a is extended by class B introducing another attribute b. Now, the private constructor of class B instantiating object B1 must be aware of attribute a and must set its value. I could not find a way to delegate construction of object B1 to construction of object A1. This tradeoff is recognized as an crucial limitation of the builder class as it breaks the concept of encapsulation. Any… Read more »

tang hao
tang hao
9 years ago

That’s really a good article to let me convert the builder pattern concept to practice. It’s fantastic. Thank you!

Justin
Justin
9 years ago

After build User Obj, the client can’t add more attribute to it. So, if i want to do that, i must provide the set method.
Ex:
public class User {

public void setPhone(String phone){
this.phone = phone;
}

}
Is it breaks builder patern’s purpose?

Jose Luis Coscia
9 years ago
Reply to  Justin

Not sure what you mean by adding more attributes to the User object but I suspect you mean changing the value of one of its fields. Given that the User class is immutable you can not have setters on it to change its state. Note however that after calling UserBuilder.build() you have all the state of the object you just created on the builder. So you can simply say: builder.phone(“new phone”).build() and you will get another User object with all its values equal to the first User object except for the phone field that will have the new value you… Read more »

Justin
Justin
9 years ago

Thanks, my mine is change value of fields as your guess.
I use builder patern to optimize my code, but sometime i want to change my object too (I don’t want to create new object), so i’m thinking about add setter method.

Stephane
Stephane
9 years ago

Great post Jose ! Thanks !

Would you show how you make the call to the buildUserCollection function and how it implements using the userBuilder parameter ?

Kind Regards,

Stephane Eybert

Stephane
Stephane
9 years ago

Hi again Jose,

I see this builder example from Petri
http://www.petrikainulainen.net/programming/unit-testing/turning-assertions-into-a-domain-specific-language/#comment-695871
and his design seems simpler.

Inside the builder, he is having a member variable for the built object, doing away with the doubling of all properties in the builder, and there seems to be no window of vulnerability either…

Thanks for the didactic article anyway !

Kind Regards,

Stephane Eybert

Stephane
Stephane
9 years ago

Hi Jose,

It’s me again :-)

One last question…

Is it okay to have several constructors and a copy constructor as well ?

Does it not defeat the whole builder idea ?

Kind Regards,

Stephane Eybert

Stephane
Stephane
9 years ago
Reply to  Stephane

The example…

public AdminBuilder(String firstname, String lastname, String email, String login) {
admin = new Admin();
admin.firstname = firstname;
admin.lastname = lastname;
admin.email = email;
admin.login = login;
}

public AdminBuilder(String email, String login) {
admin = new Admin();
admin.email = email;
admin.login = login;
}

public AdminBuilder(Admin copy) {
admin = new Admin();
BeanUtils.copyProperties(copy, admin);
}

prashanth
prashanth
9 years ago

Very nice article! Just a thought.. I don’t think it is completely thread safe when we create the object first thing in the build() method also. But, yes it reduces the “window of vulnerability”. The builder object may be worked on by two threads. While the first thread may have set the age to 110 and the second thread may have set the age to 100 just before age was being copied in the User object creation of first thread. 1. T1 : builder.setAge(110) 2. T2 : builder.setAge(100) 3. T1 : new User(this) 4. T2 : new User(this) Above two… Read more »

Rob Velseboer
Rob Velseboer
9 years ago
Reply to  prashanth

The builder object is not a singleton. You instantiate a builder that you use one to build you object with, then you discard it. If you have two threads then you would have two builders.

Peter
9 years ago
Reply to  Rob Velseboer

I think the whole discussion about thread-safety in this article can and should be removed.

Rob Velseboer
Rob Velseboer
9 years ago
Reply to  Peter

I agree, that bit is confusing.

In any typical situation the builder does not live longer than the one line of code that it is in to create your actual “User” object. You don’t even keep a reference to the builder.

Peter
9 years ago
Reply to  Rob Velseboer

Yeah, I think he should use the factory pattern then or something :)

Peter
9 years ago
Reply to  Peter
rohan
rohan
9 years ago

the example does not have comparators in the if statements :
if (age 120) {

Is that a mistake?

Attila Héjja
9 years ago

Hmm…, why you don’t use a simple structure or Properties class in the constructor? So, I think this is not the builder pattern, it more resembles to the decorator one. And this static builder class in the product class not good idea, it pulls foreign responsibilities into the product class, and so, all its accompanies. It easily could lead us to logical and architectural problems.

Siddhartha
9 years ago

This is a seriously good and useful article. Thanks.

deema
deema
8 years ago

Thank you for very clear and detailed article, Jose.
Have a (maybe) dumb question: do we really should use
User u = return new User.UserBuilder(‘Jhon’, ‘Doe’).age(30)
….
.build();

or can we use instead

User u = return User.UserBuilder(‘Jhon’, ‘Doe’).age(30)
….
.build();

Without “new User” statement?

deema
deema
8 years ago
Reply to  deema

My bad, forget to remove “return”.

deema
deema
8 years ago
Reply to  deema

Ok. We can forget my question. I just understand that we simply create new Builder instance.

Back to top button