Menu
Coddy logo textTech

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 icon

Challenge

Easy

Let'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 a Pizza class that uses the Builder Pattern for construction. Your pizza should have the following fields:

    size (String) - required, represents the pizza size

    cheese (boolean) - optional, defaults to false

    pepperoni (boolean) - optional, defaults to false

    mushrooms (boolean) - optional, defaults to false

    The Pizza constructor should be private and accept only a PizzaBuilder as 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 say no toppings.

    Create a static inner class PizzaBuilder with:

    • A constructor that takes the required size parameter
    • Methods cheese(), pepperoni(), and mushrooms() that each set their respective boolean to true and return this for chaining
    • A build() method that returns a new Pizza
  • 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 PizzaBuilder with 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, call build() 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 this for 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
        
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming