Builder Pattern

In Joshua Bloch’s ‘Effective Java’, the author discusses the use of the builder pattern as a way to efficiently instantiate an object which has many parameters (some mandatory, some optional). We’ll first look at two alternatives (Telescoping and Java Beans) before looking at the builder pattern.

Telescoping

Let’s say we have an object that will always have 2 parameters, and could have anywhere from 5 to 10 additional/optional parameters. We could have one constructor for the 2 mandatory parameters, and then another five constructors for the remaining optional parameters. This can become hard to read and write, and can introduce bugs if you get parameters in the wrong order in a long sequence of parameters.

Java Beans (using setters)

In this pattern, you create the object with a parameterless constructor, which automatically creates an object with default values. From there, you would use individual setters for each parameter you wish to set. Apparently this is can be bad practise, because the object can exist in a inconsistent state, which could introduce bugs to your code. I need to learn more about immutable objects, but this form of initialising won’t work easily with these kinds of objects.

Builder Pattern

The builder pattern gives you the readability of the Java Beans pattern, with the safety of the Telescoping pattern. Let’s look at the code:

package uk.co.richardgilmour.builderexample;

public class Book {
	// book properties
	private final String title;
	private final String author;
	private final String isbn;
	private final int pages;
	private final String publisher;

	// static member class
	public static class Builder {
		// properties all books must have
		private final String title;
		private final String author;
		// optional properties with default values
		private String isbn = "";
		private int pages = 0;
		private String publisher = "";

		public Builder(String title, String author) {
			this.title = title;
			this.author = author;
		}

		// The methods of Builder class allow the optional fields to be
		// instantiated with non-default values
		// returning the object (this) allows for method chaining

		public Builder isbn(String value) {
			isbn = value;
			return this;
		}

		public Builder pages(int value) {
			pages = value;
			return this;
		}

		public Builder publisher(String value) {
			publisher = value;
			return this;
		}

		// Calling build returns this Builder object, cast as a Book object
		// if this is not called, we would return a Builder object, not a Book
		public Book build() {
			return new Book(this);
		}
	}

	// The constructor for Book creates a builder object. Note: the Book
	// properties are all final, the only the mandatory properties of Builder
	// properties are final
	private Book(Builder builder) {
		title = builder.title;
		author = builder.author;
		isbn = builder.isbn;
		pages = builder.pages;
		publisher = builder.publisher;
	}

	// completely separate from the builder pattern, just a method of Book
	public String getAuthor() {
		return this.author;
	}
}

This book object is created like this:

Book book = new Book.Builder("Effective Java", "Joshua Bloch").isbn("99999").pages(300).build();

OK, hopefully this provides a reasonable starting point for anyone looking to implement the Builder pattern in Java. As a learner, I’d hope to update this post as I get more experience of using design patterns. I don’t claim to be an expert by any stretch of the imagination, so if you see an error or inaccuracy, please feel free to comment below!