• 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, …
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
	
	...
}

resources

next

Fluent Builder