<aside> đ đ Category: Creational Pattern
</aside>
The Builder pattern is 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.
<aside> âšī¸ When to use: When you need to create an object with many optional parameters or when the construction process must allow different representations of the object being constructed.
</aside>
Imagine a complex object that requires laborious, step-by-step initialization of many fields and nested objects. Such initialization code is usually buried inside a monstrous constructor with lots of parameters. Or even worse: scattered all over the client code.
The Builder pattern suggests that you extract the object construction code out of its own class and move it to separate objects called builders. The pattern organizes object construction into a set of steps.
public class House
{
public int Rooms { get; set; }
public int Floors { get; set; }
public bool HasGarage { get; set; }
public bool HasSwimmingPool { get; set; }
public bool HasGarden { get; set; }
public override string ToString()
{
return $"House with {Rooms} rooms, {Floors} floors, " +
$"Garage: {HasGarage}, Pool: {HasSwimmingPool}, Garden: {HasGarden}";
}
}
public interface IHouseBuilder
{
void Reset();
void SetRooms(int rooms);
void SetFloors(int floors);
void BuildGarage();
void BuildSwimmingPool();
void BuildGarden();
House GetResult();
}
public class ModernHouseBuilder : IHouseBuilder
{
private House _house;
public ModernHouseBuilder()
{
Reset();
}
public void Reset()
{
_house = new House();
}
public void SetRooms(int rooms)
{
_house.Rooms = rooms;
}
public void SetFloors(int floors)
{
_house.Floors = floors;
}
public void BuildGarage()
{
_house.HasGarage = true;
}
public void BuildSwimmingPool()
{
_house.HasSwimmingPool = true;
}
public void BuildGarden()
{
_house.HasGarden = true;
}
public House GetResult()
{
House result = _house;
Reset();
return result;
}
}
public class HouseDirector
{
private IHouseBuilder _builder;
public HouseDirector(IHouseBuilder builder)
{
_builder = builder;
}
public void ConstructLuxuryHouse()
{
_builder.Reset();
_builder.SetRooms(10);
_builder.SetFloors(3);
_builder.BuildGarage();
_builder.BuildSwimmingPool();
_builder.BuildGarden();
}
public void ConstructSimpleHouse()
{
_builder.Reset();
_builder.SetRooms(3);
_builder.SetFloors(1);
}
}
// Without Director
var builder = new ModernHouseBuilder();
builder.SetRooms(5);
builder.SetFloors(2);
builder.BuildGarage();
builder.BuildGarden();
House house1 = builder.GetResult();
// With Director
var director = new HouseDirector(builder);
director.ConstructLuxuryHouse();
House luxuryHouse = builder.GetResult();
director.ConstructSimpleHouse();
House simpleHouse = builder.GetResult();
Console.WriteLine(house1);
Console.WriteLine(luxuryHouse);
Console.WriteLine(simpleHouse);
from abc import ABC, abstractmethod
class House:
def __init__(self):
self.rooms = 0
self.floors = 0
self.has_garage = False
self.has_swimming_pool = False
self.has_garden = False
def __str__(self):
return (f"House with {self.rooms} rooms, {self.floors} floors, "
f"Garage: {self.has_garage}, Pool: {self.has_swimming_pool}, "
f"Garden: {self.has_garden}")
class HouseBuilder(ABC):
@abstractmethod
def reset(self):
pass
@abstractmethod
def set_rooms(self, rooms: int):
pass
@abstractmethod
def set_floors(self, floors: int):
pass
@abstractmethod
def build_garage(self):
pass
@abstractmethod
def build_swimming_pool(self):
pass
@abstractmethod
def build_garden(self):
pass
@abstractmethod
def get_result(self) -> House:
pass
class ModernHouseBuilder(HouseBuilder):
def __init__(self):
self.reset()
def reset(self):
self._house = House()
def set_rooms(self, rooms: int):
self._house.rooms = rooms
return self
def set_floors(self, floors: int):
self._house.floors = floors
return self
def build_garage(self):
self._house.has_garage = True
return self
def build_swimming_pool(self):
self._house.has_swimming_pool = True
return self
def build_garden(self):
self._house.has_garden = True
return self
def get_result(self) -> House:
result = self._house
self.reset()
return result
# Usage with method chaining
builder = ModernHouseBuilder()
house = (builder
.set_rooms(5)
.set_floors(2)
.build_garage()
.build_garden()
.get_result())
print(house)