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
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); }
}
}