- construct complex objects step by step
- provides flexible, readable solution for objects that may have many optional fields, large constructors with multiple parameters, and require multiple steps for construction
- modular by encapsulating building process in a separated builder class - single responsibility principle
structure
- product: object being built
- builder: interface with methods for each step of construction
- ConcreteBuilder: implements ^, and has a function like build() to retrieve final product
- director (optional): used when a specific sequence is needed to create a standard config of the product
example
StringBuilder-append()allows strings to be built step by step- http request builders
- a request has a mix of required and optional fields
- url, http method, headers, query params, request body, timeout, …
- a request has a mix of required and optional fields
class HttpRequest {
// Required
private final String url;
// Optional
private final String method;
private final Map<String, String> headers;
private final Map<String, String> queryParams;
private final String body;
private final int timeout;
// Private constructor
private HttpRequest(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers;
this.queryParams = builder.queryParams;
this.body = builder.body;
this.timeout = builder.timeout;
}
// Builder Class
public static class Builder {
private final String url; // required
private String method = "GET";
private Map<String, String> headers = new HashMap<>();
private Map<String, String> queryParams = new HashMap<>();
private String body;
private int timeout = 30000;
public Builder(String url) {
this.url = url;
}
public Builder method(String method) {
this.method = method;
return this;
}
public Builder addHeader(String key, String value) {
this.headers.put(key, value);
return this;
}
public Builder addQueryParam(String key, String value) {
this.queryParams.put(key, value);
return this;
}
public Builder body(String body) {
this.body = body;
return this;
}
public Builder timeout(int timeout) {
this.timeout = timeout;
return this;
}
public HttpRequest build() {
return new HttpRequest(this);
}
}
}a client would construct like:
HttpRequest request2 = new HttpRequest.Builder("https://api.example.com/submit")
.method("POST")
.body("{\"key\":\"value\"}")
.timeout(15000)
.build();example 2
we have a product and product stock report
public class ProductStockReport {
HeaderPart
BodyPart
FooterPart
}
public interface IProductStockReportBuilder {
BuildHeader()
BuildBody()
BuildFooter()
GetReport()
}
public class ProductStockReportBuilder : IProductStockReportBuilder {
_productStockReport
_products
...
}