A creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.
The Builder pattern is unique because it doesn't just create an object in one go; it breaks the process into independent steps. This is particularly effective when an object's construction involves many configuration options, some of which might be optional or mutually exclusive.
Avoid constructors with 10+ parameters where most are null. It makes the code cleaner and less error-prone.
By using a builder, you can collect all data first and then instantiate a 'final' object that cannot be modified after creation.
It separates the complex construction logic from the business logic of the product class itself.
You can defer certain steps, run them recursively, or skip them based on runtime conditions.
// Product Class: The complex object being built
public class GamingPC {
private final String processor;
private final String ram;
private final String gpu;
private final int storageGB;
private final boolean waterCooled;
// Private constructor: Only accessible by the Builder
private GamingPC(Builder builder) {
this.processor = builder.processor;
this.ram = builder.ram;
this.gpu = builder.gpu;
this.storageGB = builder.storageGB;
this.waterCooled = builder.waterCooled;
}
// Static inner Builder class
public static class Builder {
private String processor; // Required
private String ram; // Required
private String gpu = "Integrated"; // Optional with default
private int storageGB = 512; // Optional with default
private boolean waterCooled = false; // Optional
public Builder(String processor, String ram) {
this.processor = processor;
this.ram = ram;
}
public Builder setGpu(String gpu) {
this.gpu = gpu;
return this; // Return this for Method Chaining
}
public Builder setStorage(int gb) {
this.storageGB = gb;
return this;
}
public Builder enableWaterCooling() {
this.waterCooled = true;
return this;
}
public GamingPC build() {
// Validation can happen here before returning product
if (processor == null) throw new IllegalStateException("CPU required");
return new GamingPC(this);
}
}
}
// Usage Example
GamingPC customRig = new GamingPC.Builder("AMD Ryzen 9", "64GB")
.setGpu("RTX 4090")
.setStorage(2048)
.enableWaterCooling()
.build();An RTF Reader (Director) uses different Builders (PDFBuilder, HTMLBuilder, TeXBuilder) to convert a single document into various formats using the same parsing logic.
Creating complex mock objects for tests. Instead of setting 20 fields for a "User" object in every test, you use UserBuilder.withAdminPrivileges().build().