๐งฑ Builder Pattern โ Step-by-Step Construction
The Builder Pattern is a creational design pattern that allows step-by-step construction of complex objects. It separates the construction of a complex object from its representation so the same construction process can create different representations.
๐งฉ When to Use
- When object creation involves many steps or optional fields.
- When you need different representations of an object (e.g., HTML vs JSON).
- When constructors become overloaded with many parameters.
๐ Example 1: Building a Meal (Burger, Drink, etc.)
Problem: You want to build a meal that may contain different items like burger, drink, fries, etc. Using constructors gets messy.
Solution: Use Builder to add items step by step.
public class Meal
{
public string Main { get; set; }
public string Drink { get; set; }
public string Side { get; set; }
public override string ToString() =>
$"Main: {Main}, Drink: {Drink}, Side: {Side}";
}
public class MealBuilder
{
private Meal meal = new Meal();
public MealBuilder AddMain(string main)
{
meal.Main = main;
return this;
}
public MealBuilder AddDrink(string drink)
{
meal.Drink = drink;
return this;
}
public MealBuilder AddSide(string side)
{
meal.Side = side;
return this;
}
public Meal Build() => meal;
}
// Usage
var meal = new MealBuilder()
.AddMain("Burger")
.AddDrink("Coke")
.AddSide("Fries")
.Build();
Console.WriteLine(meal);
class Meal:
def __init__(self):
self.main = None
self.drink = None
self.side = None
def __str__(self):
return f"Main: {self.main}, Drink: {self.drink}, Side: {self.side}"
class MealBuilder:
def __init__(self):
self.meal = Meal()
def add_main(self, main):
self.meal.main = main
return self
def add_drink(self, drink):
self.meal.drink = drink
return self
def add_side(self, side):
self.meal.side = side
return self
def build(self):
return self.meal
# Usage
meal = MealBuilder().add_main("Burger").add_drink("Coke").add_side("Fries").build()
print(meal)
๐งฑ Example 2: Director with Multiple Builders
Scenario: You want to create different types of houses using the same steps โ foundation, walls, roof.
public class House
{
public string Foundation { get; set; }
public string Walls { get; set; }
public string Roof { get; set; }
public override string ToString() =>
$"Foundation: {Foundation}, Walls: {Walls}, Roof: {Roof}";
}
public abstract class HouseBuilder
{
protected House house = new House();
public abstract void BuildFoundation();
public abstract void BuildWalls();
public abstract void BuildRoof();
public House GetResult() => house;
}
public class WoodenHouseBuilder : HouseBuilder
{
public override void BuildFoundation() => house.Foundation = "Wood Poles";
public override void BuildWalls() => house.Walls = "Wood Panels";
public override void BuildRoof() => house.Roof = "Wooden Shingles";
}
public class Director
{
public void Construct(HouseBuilder builder)
{
builder.BuildFoundation();
builder.BuildWalls();
builder.BuildRoof();
}
}
// Usage
var builder = new WoodenHouseBuilder();
var director = new Director();
director.Construct(builder);
Console.WriteLine(builder.GetResult());
class House:
def __init__(self):
self.foundation = None
self.walls = None
self.roof = None
def __str__(self):
return f"Foundation: {self.foundation}, Walls: {self.walls}, Roof: {self.roof}"
class HouseBuilder:
def __init__(self):
self.house = House()
def build_foundation(self): pass
def build_walls(self): pass
def build_roof(self): pass
def get_result(self):
return self.house
class WoodenHouseBuilder(HouseBuilder):
def build_foundation(self):
self.house.foundation = "Wood Poles"
def build_walls(self):
self.house.walls = "Wood Panels"
def build_roof(self):
self.house.roof = "Wooden Shingles"
class Director:
def construct(self, builder):
builder.build_foundation()
builder.build_walls()
builder.build_roof()
# Usage
builder = WoodenHouseBuilder()
director = Director()
director.construct(builder)
print(builder.get_result())
๐ Key Points
Feature | Description |
---|---|
Pattern Type | Creational |
Key Participants | Builder, Product, Director |
Fluent Interface | Improves readability by chaining methods |
Benefit | Separate construction from representation |