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.
// ─── 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);
}
}