Design Pattern

Builder Pattern

Clean Java-only production-ready implementation.


What Problem It Solves

When an object has 8+ parameters (many optional), constructors become unreadable and error-prone. new House(4, 2, true, false, true, null, null, "tile") โ€” is that 4 bedrooms or 4 bathrooms? Builder solves this with named, chainable setters.

Builder vs Constructor

AspectConstructor / TelescopingBuilder
ReadabilityPositional โ€” easy to misorder paramsNamed methods โ€” self-documenting
Optional paramsMany overloads (explosive)Only set what you need
ImmutabilityYes (final fields)Yes (build() creates immutable object)
ValidationAt constructionIn build() method

Where Builder Appears in LLD

  • Hotel Booking (#16): Search filters (city, dates, guests, amenities, price range)
  • Email (#57): new EmailBuilder().to("x").subject("y").body("z").attach("f").build()
  • Logger Config (#15): LoggerConfig.builder().level("INFO").format("JSON").output("stdout").build()
  • Search (#25): Query builder with filters, sorting, pagination

Implementation

// โ”€โ”€โ”€ EXAMPLE 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// WHAT WE ARE IMPLEMENTING:
// A complex rich-text Document exporter assembling headers, bodies, and
// footers step-by-step.
//
// WHERE THE PATTERN FITS IN:
// DocumentBuilder acts as the Builder interface, defining individual assembly
// operations. Document is the Product being built.
// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// --- Product ---
class HotelBooking {
    private final String city;
    private final String checkIn;
    private final String checkOut;
    private final int guests;
    private final boolean breakfast;
    private final boolean parking;
    private final boolean poolAccess;
    private final String roomType;

    // Private constructor โ€” only called by Builder
    private HotelBooking(String city, String checkIn, String checkOut, int guests,
                         boolean breakfast, boolean parking, boolean poolAccess, String roomType) {
        this.city = city; this.checkIn = checkIn; this.checkOut = checkOut;
        this.guests = guests; this.breakfast = breakfast;
        this.parking = parking; this.poolAccess = poolAccess; this.roomType = roomType;
    }

    public static class Builder {
        // Required params
        private final String city;
        private final String checkIn;
        private final String checkOut;

        // Optional params with defaults
        private int guests = 1;
        private boolean breakfast = false;
        private boolean parking = false;
        private boolean poolAccess = false;
        private String roomType = "STANDARD";

        public Builder(String city, String checkIn, String checkOut) {
            this.city = city;
            this.checkIn = checkIn;
            this.checkOut = checkOut;
        }

        public Builder guests(int guests) { this.guests = guests; return this; }
        public Builder breakfast(boolean v) { this.breakfast = v; return this; }
        public Builder parking(boolean v) { this.parking = v; return this; }
        public Builder poolAccess(boolean v) { this.poolAccess = v; return this; }
        public Builder roomType(String type) { this.roomType = type; return this; }

        public HotelBooking build() {
            if (checkIn.compareTo(checkOut) >= 0) throw new IllegalArgumentException("check-out must be after check-in");
            return new HotelBooking(city, checkIn, checkOut, guests, breakfast, parking, poolAccess, roomType);
        }
    }

    @Override
    public String toString() {
        return "HotelBooking{city=" + city + ", dates=" + checkIn + " to " + checkOut +
               ", guests=" + guests + ", room=" + roomType +
               ", breakfast=" + breakfast + ", parking=" + parking + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        // Readable, intentional, no wrong-order bugs
        HotelBooking booking = new HotelBooking.Builder("Mumbai", "2025-06-01", "2025-06-05")
            .guests(2)
            .breakfast(true)
            .parking(true)
            .roomType("DELUXE")
            .build();

        System.out.println(booking);
    }
}

๐Ÿ’ฌReview

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...