Builder Pattern
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 67 of 87.
The Builder Pattern is a creational design pattern that solves a common problem: constructing complex objects with many optional parameters. Instead of creating multiple constructors or passing null for unused parameters, the Builder lets you construct objects step by step.
Consider creating a User object with required fields (name, email) and optional ones (age, phone, address). Without a Builder, you'd need telescoping constructors or a messy constructor with many parameters. The Builder pattern offers a cleaner approach:
public class User {
private final String name; // required
private final String email; // required
private final int age; // optional
private final String phone; // optional
private User(UserBuilder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phone = builder.phone;
}
public static class UserBuilder {
private final String name;
private final String email;
private int age;
private String phone;
public UserBuilder(String name, String email) {
this.name = name;
this.email = email;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public User build() {
return new User(this);
}
}
}The Builder's methods return this, enabling method chaining—a fluent, readable way to construct objects:
User user = new User.UserBuilder("Alice", "alice@email.com")
.age(25)
.phone("555-1234")
.build();Notice how the User constructor is private—objects can only be created through the Builder. This pattern shines when objects have many optional fields, making your code more readable and less error-prone than long parameter lists.
Challenge
EasyLet's build a pizza ordering system using the Builder Pattern! Instead of dealing with a constructor that takes dozens of parameters for all possible toppings and options, you'll create a fluent builder that makes pizza customization clean and readable.
You'll organize your code across two files:
Pizza.java: Create aPizzaclass that uses the Builder Pattern for construction. Your pizza should have the following fields:size(String) - required, represents the pizza sizecheese(boolean) - optional, defaults to falsepepperoni(boolean) - optional, defaults to falsemushrooms(boolean) - optional, defaults to falseThe
Pizzaconstructor should be private and accept only aPizzaBuilderas its parameter, copying all values from the builder to the pizza's fields.Include a
getDescription()method that returns a string in this format:[size] Pizza with: [toppings]where toppings is a comma-separated list of the toppings that are true (Cheese, Pepperoni, Mushrooms). If no toppings are selected, the toppings part should just sayno toppings.Create a static inner class
PizzaBuilderwith:- A constructor that takes the required
sizeparameter - Methods
cheese(),pepperoni(), andmushrooms()that each set their respective boolean to true and returnthisfor chaining - A
build()method that returns a newPizza
- A constructor that takes the required
Main.java: Demonstrate your pizza builder in action! You'll receive four inputs: the pizza size (String), and three yes/no values (Strings) indicating whether to add cheese, pepperoni, and mushrooms respectively.Create a
PizzaBuilderwith the given size. Then, based on each yes/no input, chain the appropriate topping methods. If the input is"yes", call that topping method; if"no", skip it. Finally, callbuild()to create your pizza.Print the result of calling
getDescription()on your completed pizza.
You will receive four inputs in order: size (String), add cheese (String: "yes" or "no"), add pepperoni (String: "yes" or "no"), add mushrooms (String: "yes" or "no").
For example, with inputs Large, yes, no, yes, your output would be: Large Pizza with: Cheese, Mushrooms
Notice how the Builder Pattern lets you construct pizzas with any combination of toppings without needing separate constructors for each possibility!
Cheat sheet
The Builder Pattern is a creational design pattern for constructing complex objects with many optional parameters. It avoids telescoping constructors and long parameter lists by building objects step by step.
Structure
The pattern consists of:
- A class with a private constructor that accepts only a builder
- A static inner Builder class that constructs the object
- Builder methods that return
thisfor method chaining - A
build()method that creates the final object
Implementation Example
public class User {
private final String name; // required
private final String email; // required
private final int age; // optional
private final String phone; // optional
private User(UserBuilder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phone = builder.phone;
}
public static class UserBuilder {
private final String name;
private final String email;
private int age;
private String phone;
public UserBuilder(String name, String email) {
this.name = name;
this.email = email;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public User build() {
return new User(this);
}
}
}Usage with Method Chaining
User user = new User.UserBuilder("Alice", "alice@email.com")
.age(25)
.phone("555-1234")
.build();The Builder pattern is ideal when objects have many optional fields, providing readable and maintainable code compared to constructors with numerous parameters.
Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String size = scanner.nextLine();
String addCheese = scanner.nextLine();
String addPepperoni = scanner.nextLine();
String addMushrooms = scanner.nextLine();
// TODO: Create a PizzaBuilder with the given size
// TODO: Chain topping methods based on yes/no inputs
// TODO: Build the pizza and print its description
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternBuilder PatternObserver PatternStrategy Pattern3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System