creational

Builder

Separate the construction of a complex object from its representation so the same process can create different representations.

Some objects have a lot of fields, and most are optional.

Put them all in a constructor and you get calls like new Pizza(12, true, false, true, 2, false). Nobody can read that. Which true was extra cheese? Write one constructor per combination and you end up with dozens.

Builder lets you set fields one at a time, by name, and then build the object at the end. The call reads like a description of what you want.

What the interviewer is probing.

1. "What problem does Builder solve?" *Probing:* the motivation. *Stalls:* "Building objects." *Moves up:* the telescoping constructor — many optional parameters, where positional arguments become unreadable and error-prone.

2. "How does it help immutability?" *Probing:* the connection. *Stalls:* "It does not." *Moves up:* the object is assembled in the builder and constructed once, so the result can be fully final with no setters.

3. "When is it unnecessary?" *Probing:* judgement. *Stalls:* "Never." *Moves up:* with few parameters, or in a language with named and default arguments, which solve the same problem natively.

4. "What validation belongs where?" *Probing:* the depth. *Stalls:* "In the setters." *Moves up:* cross-field validation in build(), since individual setters cannot see the final combination.

Ordering a custom pizza — you pick crust, sauce, toppings one by one. The kitchen only bakes it once you say done.

Key Concepts

1
A separate builder object collects the values. Each setter returns the builder itself, so calls can be chained: .size(12).cheese(true).build().
.size(12).cheese(true).build()
2
Nothing is created until you call build(). That method runs the validation and returns the finished object. Because the object is only assembled once, at the end, its fields can be final and it can be immutable.
build()final
3
build() is also where you check that required fields were actually set. Without that check, the pattern happily gives you a half-filled object.
build()
java
public class HttpRequest {
    private final String url;
    private final String method;
    private final Map<String, String> headers;

    private HttpRequest(Builder b) {
        this.url = b.url;
        this.method = b.method;
        this.headers = b.headers;
    }

    public static class Builder {
        private final String url;
        private String method = "GET";
        private Map<String, String> headers = new HashMap<>();

        public Builder(String url) { this.url = url; }
        public Builder method(String m) { this.method = m; return this; }
        public Builder header(String k, String v) { headers.put(k, v); return this; }
        public HttpRequest build() { return new HttpRequest(this); }
    }
}