0Pricing
Java Academy · Lesson

Builder Pattern with Fluent API

Construct complex objects step-by-step with a fluent builder to avoid telescoping constructors.

Builder Pattern with Fluent API is a free Java Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Telescoping Constructor Problem

When a class has many optional parameters, constructors multiply: 2-param, 3-param, 4-param... The Builder pattern solves this with a fluent step-by-step configuration API.

// Without builder — hard to read:
Pizza p = new Pizza("large", "thin", true, false, true, false, "mozzarella");

Basic Builder Structure

Create a static nested Builder class. The outer class has a private constructor that accepts the builder. Each setter in the builder returns this for fluent chaining.

public final class Pizza {
    private final String size, crustType, cheese;
    private final boolean extraSauce, pepperoni;
    private Pizza(Builder b) {
        this.size = b.size; this.crustType = b.crustType;
        this.cheese = b.cheese; this.extraSauce = b.extraSauce;
        this.pepperoni = b.pepperoni;
    }
    public static class Builder {
        private final String size;
        private String crustType = "regular", cheese = "mozzarella";
        private boolean extraSauce, pepperoni;
        public Builder(String size) { this.size = size; }
        public Builder crustType(String c) { this.crustType = c; return this; }
        public Builder cheese(String c)    { this.cheese = c;    return this; }
        public Builder extraSauce()        { this.extraSauce = true; return this; }
        public Builder pepperoni()         { this.pepperoni = true; return this; }
        public Pizza build()               { return new Pizza(this); }
    }
}

Fluent API Usage

The builder reads like a sentence. Required parameters go in the constructor; optional ones are method calls. The final build() call produces the immutable object.

Pizza p = new Pizza.Builder("large")
    .crustType("thin")
    .extraSauce()
    .pepperoni()
    .build();
System.out.println(p);

Validation in build()

Add validation logic inside build() before constructing the object. Throw IllegalStateException or IllegalArgumentException for invalid combinations.

public Pizza build() {
    if (size == null || size.isBlank())
        throw new IllegalArgumentException("Size required");
    if (extraSauce && crustType.equals("stuffed"))
        throw new IllegalStateException("No extra sauce on stuffed crust");
    return new Pizza(this);
}

Builder for Immutable Objects

Because the outer class is created from the builder in one shot, all fields can be final — making the resulting object fully immutable and thread-safe.

public final class Address {
    private final String street, city, country;
    private final String postalCode;
    private Address(Builder b) { ... } // all finals
    // no setters — immutable!
}

Generic Builder with Self-Type

For inheritance hierarchies, use a recursive generic type parameter (SELF extends Builder<SELF>) so subclass builders return the subclass type from chained methods.

public abstract static class Builder<SELF extends Builder<SELF>> {
    String name;
    @SuppressWarnings("unchecked")
    public SELF name(String n) { this.name = n; return (SELF) this; }
    public abstract Vehicle build();
}

Lombok @Builder

Lombok's @Builder generates the entire builder infrastructure at compile time. Use @Builder.Default for default field values and @Singular for collections.

@Builder
public class Report {
    private final String title;
    @Builder.Default private final int pageCount = 1;
    @Singular private final List<String> authors;
}
// Usage:
Report r = Report.builder().title("Q4").author("Alice").author("Bob").build();

Builder in the JDK

Many JDK classes use builder-style APIs: StringBuilder, HttpRequest.newBuilder(), ProcessBuilder, Stream.Builder. Recognize the pattern.

HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Accept", "application/json")
    .GET()
    .build();

Builder vs Factory

Use Builder when an object requires many parameters and step-by-step configuration. Use Factory when all variants are simple and creation can be done in one call.

Builder for Test Data

Builders shine in tests: create a base builder in a helper, then override just the fields relevant to each test case — keeping tests DRY and readable.

User defaultUser() { return new User.Builder("test@example.com").name("Test User").build(); }
User adminUser()   { return new User.Builder("admin@example.com").name("Admin").role(ADMIN).build(); }

Thread Safety

The builder itself is not thread-safe — don't share a Builder across threads. The product built from it can be immutable and thread-safe if all fields are final and no mutable objects are shared.

Quick Check

What makes a builder method "fluent"?

Recap

Builder solves the telescoping constructor problem. Use a static nested Builder class, return this from each setter, validate in build(), and produce an immutable object. Lombok @Builder automates the boilerplate.

Frequently asked questions

Is the “Builder Pattern with Fluent API” lesson free?

Yes — the full text of “Builder Pattern with Fluent API” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “Builder Pattern with Fluent API”?

Construct complex objects step-by-step with a fluent builder to avoid telescoping constructors. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Builder Pattern with Fluent API” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Singleton: Thread-Safe Implementations
  2. Factory Method Pattern
  3. Abstract Factory for Product Families
  4. Builder Pattern with Fluent API
← Back to Java Academy