Dezign Patterns
Builder Design Pattern
The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.
// Product class
class Computer {
// Required parameters
private final String CPU;
private final String RAM;
// Optional parameters
private final int storage;
private final boolean isGraphicsCardEnabled;
private final boolean isBluetoothEnabled;
// Private constructor to enforce object creation via Builder
private Computer(Builder builder) {
this.CPU = builder.CPU;
this.RAM = builder.RAM;
this.storage = builder.storage;
this.isGraphicsCardEnabled = builder.isGraphicsCardEnabled;
this.isBluetoothEnabled = builder.isBluetoothEnabled;
}
// Static Builder class
public static class Builder {
// Required parameters
private final String CPU;
private final String RAM;
// Optional parameters - initialized to default values
private int storage = 256; // default in GB
private boolean isGraphicsCardEnabled = false;
private boolean isBluetoothEnabled = false;
// Builder constructor with required parameters
public Builder(String CPU, String RAM) {
this.CPU = CPU;
this.RAM = RAM;
}
// Setter methods for optional parameters
public Builder setStorage(int storage) {
this.storage = storage;
return this;
}
public Builder enableGraphicsCard(boolean enabled) {
this.isGraphicsCardEnabled = enabled;
return this;
}
public Builder enableBluetooth(boolean enabled) {
this.isBluetoothEnabled = enabled;
return this;
}
// build() method to return the final Computer object
public Computer build() {
return new Computer(this);
}
}
@Override
public String toString() {
return "Computer [CPU=" + CPU + ", RAM=" + RAM + ", Storage=" + storage +
"GB, GraphicsCard=" + isGraphicsCardEnabled +
", Bluetooth=" + isBluetoothEnabled + "]";
}
}
// Demo class
public class BuilderPatternDemo {
public static void main(String[] args) {
// Using Builder to create object
Computer myComputer = new Computer.Builder("Intel i7", "16GB")
.setStorage(512)
.enableGraphicsCard(true)
.enableBluetooth(true)
.build();
System.out.println(myComputer);
}
}
✅ Advantages of the Builder Pattern
- Helps avoid constructor overloading.
- Improves readability when creating complex objects.
- Makes object construction step-by-step and flexible.
❌ Disadvantages of the Builder Pattern
- Increased Code Complexity
It introduces additional classes (Builder, Director if used), which increases the number of code files and overall complexity. For simple objects, the Builder Pattern may be overkill. - Boilerplate Code
You often end up writing a lot of repetitive code, especially for classes with many fields (getters, setters, builders, etc.). - Not Suitable for All Scenarios
It's mainly beneficial for constructing complex or immutable objects. For simpler or mutable objects, regular constructors or setters may be more straightforward. - Requires Careful Synchronization (in multithreaded environments)
If multiple threads share a builder instance, you must ensure it's thread-safe, which can add more overhead. - May Hide Dependencies
Unlike constructors that clearly show required dependencies, builder-based instantiation may obscure what parameters are truly necessary if the builder is misused. - Potential for Incomplete Objects
If the builder is used incorrectly or partially, it may result in invalid or incomplete objects unless proper validation is added in the build() method.