Low-Level Design Tutorial 0/42 lessons ~6 min read Lesson 23

    Builder Pattern

    The Builder pattern constructs complex objects step by step — ideal when many optional fields, validation rules, or immutable products make telescoping constructors unreadable.

    Course progress0%
    Focus
    9 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    The Builder pattern constructs complex objects step by step — ideal when many optional fields, validation rules, or immutable products make telescoping constructors unreadable. Think HttpRequest, PizzaOrder, or GameBoard with configurable size and snakes.

    Java records plus compact constructors cover simple cases; Builder shines when defaults, validation, and fluent API improve clarity in LLD interviews.

    Distinguish Builder from Factory: Builder assembles one product; Factory selects among products.

    Understanding the topic

    Key concepts

    • Separate construction from representation.
    • Fluent interface: chained setter-like methods.
    • build() validates and returns immutable product.
    • Director optional — orchestrates build steps.
    • Java records: builder for many optional fields.
    • Static inner Builder common in Java LLD.

    Step-by-step explanation

    1. Define immutable product with required fields.
    2. Create Builder with defaults for optional fields.
    3. Each builder method returns this for chaining.
    4. build() checks invariants, constructs product.
    5. Reject build() if required fields missing.
    6. Client uses builder at composition root.

    Informative example

    Snake and Ladder board built with fluent builder:

    java
    public final class GameBoard {
    private final int size;
    private final Map<Integer, Integer> jumps;
    private GameBoard(int size, Map<Integer, Integer> jumps) {
    this.size = size;
    this.jumps = Map.copyOf(jumps);
    }
    public static Builder builder(int size) { return new Builder(size); }
    public static final class Builder {
    private final int size;
    private final Map<Integer, Integer> jumps = new HashMap<>();
    private Builder(int size) {
    if (size <= 0) throw new IllegalArgumentException("size");
    this.size = size;
    }
    public Builder snake(int from, int to) {
    jumps.put(from, to);
    return this;
    }
    public Builder ladder(int from, int to) {
    jumps.put(from, to);
    return this;
    }
    public GameBoard build() {
    jumps.forEach((from, to) -> {
    if (from < 1 || from > size) throw new IllegalStateException("invalid from");
    });
    return new GameBoard(size, jumps);
    }
    }
    }

    Builder collects snakes/ladders before immutable GameBoard creation — clear interview narrative.

    Real-world use

    Real-world applications

    • Complex DTOs with many optional parameters.
    • Test data setup in unit tests.
    • Configuration objects (ElevatorConfig, ParkingLotLayout).

    Best practices

    • Make product immutable after build().
    • Validate only in build(), not every setter.
    • Required fields via constructor args to Builder.
    • Consider static factory when fields are few.
    • Name builder methods domain-specific (withSnake not setJump).

    Common mistakes

    • Builder for two-field objects (overkill).
    • Mutable product after build.
    • Partially built object escaping before build().
    • Duplicating validation in builder and product.

    Advanced interview questions

    Q1BeginnerWhen use Builder pattern?
    Many optional parameters, complex validation, or stepwise assembly.
    Q2BeginnerBuilder vs constructor?
    Builder improves readability when combinations explode; constructor fine for few required fields.
    Q3IntermediateShould build() be idempotent?
    Typically no — each build creates new product; reuse builder carefully.
    Q4IntermediateJava records with Builder?
    Use builder when record has many optional fields; record alone when all required.
    Q5AdvancedBuild immutable ParkingLot with floors and spots.
    ParkingLotBuilder.addFloor(level, compactCount, largeCount).build() validates capacity and returns immutable layout.

    Summary

    Builder assembles complex objects stepwise. Fluent API + build() validation. Immutable products after construction. Use when constructors become unmanageable. Distinct from Factory variant selection.

    Ready to mark this lesson complete?Track your journey across the entire course.