Builder Pattern

Builder pattern helps us create immutable class instances. Instances that you set their state once and don’t change it for the rest of the program. By not having setters and only initialize fields through constructors the object is immutable.

public User (String firstName, String lastName, int age, String phone){ }
public User (String firstName, String lastName, String phone, String address){ }
public User (String firstName, String lastName, int age){ }
public User (String firstName, String lastName){ }

The problem is with this approach is that the number constructors to create can be too many to maintain properly. If we add setters we will lose immutability. This is where the Builder pattern comes into the picture.

How to implement:

  1. Create an immutable class with private fields and no setters.
  2. The immutable class must have one private constructor that takes a builder parameter.
  3. Create an inner public static class Builder within the immutable class.
  4. Set up a way to create Builder. Here I am using a method named public static UserBuilder standard() to get the Builder instance.
  5. Create methods to set Builder state and return Builder as a return type.
  6. Create a build method which creates the immutable class instance.
public class User {
	
	private String firstName;
	private String lastName;
	private int age;
	private String phone;

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

	//---- all getters no setters
	
	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	public String getPhone() {
		return phone;
	}

	public static class UserBuilder {
		private String firstName;
		private String lastName;
		private int age;
		private String phone;
		
		private UserBuilder() {}

		public static UserBuilder standard() {
			return new UserBuilder();
		}
		
		public static User defaultClient() {
			return new UserBuilder().build();
		}
		
		public UserBuilder firstName(String firstName) {
			this.firstName = firstName;
			return this;
		}
		
		public UserBuilder lastName(String lastName) {
			this.lastName = lastName;
			return this;
		}

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

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

		public User build() {
			User user = new User(this);
			validateUserObject(user);
			return user;
		}

		// validate user object
		private void validateUserObject(User user) {
			
		}
	}
}

Main class

public class BuilderMain {

	public static void main(String[] args) {
		
		User user = UserBuilder.standard()
				.age(12)
				.phone("3101234567")
				.firstName("Folau")
				.lastName("Kaveinga")
				.build();
		
		System.out.println(ObjectUtils.toJson(user));
	}

}

Something developers need to keep track of is that when adding a new field to the immutable class it needs to be added to the builder as well.

Advantages

  1. Highly readable code since there is not a lot of constructors to read through and figure out what they do.
  2. The immutable object will always be instantiated completely before being used.
  3. Not a lot of logic for creating an immutable object.

Disadvantages

  1. The number of lines of code double because of the builder class having all attributes of the immutable class.

Source code on Github




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *