Builder Design Pattern: Simplifying Complex Object Creation
The Builder Design Pattern is a creational design pattern that helps you construct complex objects step by step. It separates the construction of an object from its representation, allowing you to create different configurations of the same object without cluttering your code with multiple constructors.
Example: Building a Pizza
Let’s say you’re building a pizza ordering system. A pizza can have various attributes like size, crust type, toppings, and cheese. Instead of creating a constructor with many parameters, you can use the Builder Pattern to simplify the process.
Step-by-Step Implementation
Step 1: Create the Pizza
Class
This is the complex object we want to build.
public class Pizza {
private String size;
private String crust;
private List<String> toppings;
private boolean extraCheese;
// Private constructor to force use of Builder
private Pizza(PizzaBuilder builder) {
this.size = builder.size;
this.crust = builder.crust;
this.toppings = builder.toppings;
this.extraCheese = builder.extraCheese;
}
// Getters for Pizza attributes
public String getSize() {
return size;
}
public String getCrust() {
return crust;
}
public List<String> getToppings() {
return toppings;
}
public boolean isExtraCheese() {
return extraCheese;
}
@Override
public String toString() {
return "Pizza [size=" + size + ", crust=" + crust + ", toppings=" + toppings + ", extraCheese=" + extraCheese + "]";
}
// Step 2: Create the Builder class
public static class PizzaBuilder {
private String size;
private String crust;
private List<String> toppings = new ArrayList<>();
private boolean extraCheese;
public PizzaBuilder(String size, String crust) {
this.size = size;
this.crust = crust;
}
public PizzaBuilder addTopping(String topping) {
this.toppings.add(topping);
return this;
}
public PizzaBuilder setExtraCheese(boolean extraCheese) {
this.extraCheese = extraCheese;
return this;
}
public Pizza build() {
return new Pizza(this);
}
}
}
Step 3: Use the Builder to Create a Pizza
Now, you can create a Pizza
object step by step using the PizzaBuilder
.
public class Main {
public static void main(String[] args) {
// Create a custom pizza using the Builder
Pizza myPizza = new Pizza.PizzaBuilder("Large", "Thin Crust")
.addTopping("Mushrooms")
.addTopping("Olives")
.setExtraCheese(true)
.build();
// Print the pizza details
System.out.println(myPizza);
}
}
Output
Pizza [size=Large, crust=Thin Crust, toppings=[Mushrooms, Olives], extraCheese=true]
Key Points About the Builder Pattern
Step-by-Step Construction: You can add attributes to the object one at a time.
Fluent Interface: The builder methods return the builder itself, allowing method chaining.
Immutable Object: Once the object is built, it cannot be modified, ensuring thread safety.
When to Use the Builder Pattern?
When an object has many optional parameters.
When you want to create immutable objects.
When you need to construct different configurations of the same object.