The builder pattern is a type of design pattern template for solving pro­gram­ming tasks in object-oriented pro­gram­ming. Builder patterns make pro­gram­ming easier for de­velopers, because not every step that occurs re­peatedly has to be re-designed as a program routine.

Instead, an es­tab­lished solution can be used. The software elements are based on the book ‘Design Pattern: Elements of Reusable Object-Oriented Software’ published in 1994 by four US software de­velopers – known as the Gang of Four, or GoF for short. Our guide in­tro­duces you to the essential aspects of the builder design pattern including a practical example.

The builder pattern in detail

The builder pattern belongs to the group of con­struc­tion patterns within design patterns. It improves both the security of con­struct­ing and the read­ab­il­ity of the program code. The aim of the builder design pattern is to create an object without known con­struct­ors, but with an auxiliary class.

Quote

‘Separate the con­struc­tion of a complex object from its rep­res­ent­a­tion so that the same con­struc­tion process can create different rep­res­ent­a­tions.’

- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (= ‘Gang of Four’)

Source: Design Patterns: Elements of Reusable Object-Oriented Software 1. Edition, Publisher: Addison-Wesley Pro­fes­sion­al; 1. Edition (10th November 1994)

A builder design pattern dis­tin­guishes between four actors:

  • Director: This actor con­structs the complex object using the interface of the builder. They are aware of the sequence re­quire­ments of the builder. With the director, the con­struc­tion of an object is decoupled from the customer (‘client’).
  • Builder: Provides an interface for creating the com­pon­ents of a complex object (or product).
  • Specific builder: This actor creates the parts of the complex object and defines (and manages) the rep­res­ent­a­tion of the object, and maintains an interface for the output of the object.
  • Product: The result of the ‘activity’ of the builder pattern, i.e. the complex object to be con­struc­ted.

The director oversees the decisive process of the builder pattern: the sep­ar­a­tion of the creation of an object/product from the client.

UML present­a­tion of the builder pattern

The Unified Modeling Language, in short UML, is useful to graph­ic­ally represent the pro­gram­ming processes. The graphic shows that the builder pattern consists of several objects that interact with one another.

Pros and cons of the design pattern

Here’s a look at the pros and cons.

Pros of builder pattern

The con­struc­tion and rep­res­ent­a­tion (output) are in­cor­por­ated sep­ar­ately. The internal rep­res­ent­a­tions of the builder are hidden from the director. As such, new rep­res­ent­a­tions can easily be in­teg­rated through the use of concrete building classes. The process of con­struc­tion is con­trolled by the director ex­pli­citly. If changes need to be made, this can be done without con­sult­ing the client.

Cons of builder pattern

The builder pattern consists of a close coupling between the product, the specific builder, and the classes involved in the design process, so changes to the basic process can be difficult. The building (con­struc­tion) of the objects often requires knowledge of their specific use and their en­vir­on­ment. The use of known patterns, including the builder design pattern, can lead pro­gram­mers to overlook simpler and more elegant solutions. Ul­ti­mately, many pro­gram­mers consider the builder pattern as one of the less important design patterns.

When is the builder pattern used?

One way to il­lus­trate the builder design pattern is to consider the example of a res­taur­ant and a customer placing an order. Once the order has been received, the res­taur­ant employees act to carry it out. The entire process up until the order delivery takes place ‘behind the scenes’. The guest doesn’t see what happens in the kitchen, for example, they’re ul­ti­mately being served the result (in pro­gram­ming language: print).

The following code examples further highlight the in­di­vidu­al actors of the builder pattern.

The object, i.e. the menu, is empty to begin with. Content is added once an order is made:

public class Menu {
	private String starter = "No starter";
	private String maincourse = "No main course";
	private String dessert = "No dessert";
	private String drink = "No drink";
	public void setstarter (String starter) {
		this.starter = starter;
	}
	public void setmaincourse (String maincourse) {
		this.maincourse = maincourse;
	}
	public void setdessert(String dessert) {
		this.dessert = dessert;
	}
	public void setdrink(String drink) {
		this.drink = drink;
	}
	public void print() {
		System.out.println(
			"The food is ready! " + "\n" +
			" – Starter: " + starter +
			" – Main course: " + maincourse +
			" – Dessert: " + dessert +
			" – Drink: " + drink);
	}
}

The director provides the ‘en­vir­on­ment’ so that a dish can be prepared – or built – for the guest. This en­vir­on­ment is ac­cess­ible to every guest. The guest only com­mu­nic­ates with the director, so that the actual pre­par­a­tion remains hidden:

public class MattsRestaurant {
	private MenuBuilder menuBuilder;
	public void setBuilder(MenuBuilder menuBuilder) {
		this.menuBuilder = menuBuilder;
	}
	public Menu buildMenu(){
		menuBuilder.buildStarter();
		menuBuilder.buildMainCourse();
		menuBuilder.buildDessert();
		menuBuilder.buildDrink();
		return menuBuilder.build();
	}
}

Then the builder steps into action. In our example, this would be a chef:

public abstract class MenuBuilder {
	Menu menu = new Menu();
	abstract void buildStarter();
	abstract void buildMainCourse();
	abstract void buildDessert();
	abstract void buildDrink();
	Menu build()
{
		return menu;
	}
}

The specific builder, in this case the cook, builds (i.e. cooks) the in­di­vidu­al com­pon­ents of the ordered dish. To do this, they override the ‘abstract’ menu items:

public class MenuOfTheDayBuilder extends MenuBuilder {
	@Override
	public void buildStarter() {
		burger.setStarter("Pumpkin soup");
	}
	@Override
	public void buildMainCourse() {
		burger.setMainCourse("Grilled steak with potatoes");
	}
	@Override
	public void buildDessert() {
		burger.setDessert("Vanilla ice cream");
	}
	@Override
	public void buildDrink() {
		burger.setDrink("Red wine");
	}
}

Lastly, the in­di­vidu­al com­pon­ents of the dish are sum­mar­ised and delivered to the guest, i.e. ‘printed out’.

public class Main {
	public static void main(String[] args) {
		MattsRestaurant mattsRestaurant = new MattsRestaurant();
		menuRestaurant.setBuilder(new MenuOfTheDayBuilderBuilder());
		buildMenu(menuRestaurant);
		menuRestaurant.setBuilder(new SpecialMenuBuilder());
		buildMenu(menuRestaurant);
	}
	private static void buildMenu(MattsRestaurant mattsRestaurant) {
		MenuOfTheDay menu = mattsRestaurant.buildMenu();
		menu.print();
	}
}
Note

This example is based on code written by Daniel Høyer Jacobsen, which is available on his website Design Patterns in Java.

Go to Main Menu