Skip to content

Builder Pattern

Category: Creational Pattern

Overview

Separate the construction of a complex object from its representation, allowing the same construction process to create different representations. This pattern provides a step-by-step approach to constructing objects, particularly useful when objects require many configuration parameters or complex initialization.

Usage Guidelines

Use when:

  • Object creation involves many steps or configuration options
  • Same construction process should create different representations
  • Many optional parameters would lead to multiple constructors
  • Building immutable objects step by step before finalization

Avoid when:

  • Object has few parameters and simple construction
  • Object always created the same way
  • Builder adds unacceptable performance overhead
  • Python dataclasses or named tuples work well

Implementation

from __future__ import annotations

class Computer:
    """Represents a computer with various components.

    This is the product class that the builder constructs.
    """

    def __init__(self) -> None:
        """Initialize an empty computer."""
        self.cpu: str | None = None
        self.ram: int | None = None
        self.storage: str | None = None
        self.gpu: str | None = None
        self.os: str | None = None
        self.peripherals: list[str] = []

    def get_specifications(self) -> str:
        """Get the computer specifications as a formatted string.

        Returns:
            A string representation of the computer specifications.
        """
        specs = []
        if self.cpu:
            specs.append(f"CPU: {self.cpu}")
        if self.ram:
            specs.append(f"RAM: {self.ram}GB")
        if self.storage:
            specs.append(f"Storage: {self.storage}")
        if self.gpu:
            specs.append(f"GPU: {self.gpu}")
        if self.os:
            specs.append(f"OS: {self.os}")
        if self.peripherals:
            specs.append(f"Peripherals: {', '.join(self.peripherals)}")
        return "\n".join(specs) if specs else "No specifications set"

class ComputerBuilder:
    """Builder for constructing Computer objects.

    This builder uses method chaining (fluent interface) to set component properties.
    """

    def __init__(self) -> None:
        """Initialize the builder with a new Computer instance."""
        self._computer = Computer()

    def set_cpu(self, cpu: str) -> ComputerBuilder:
        """Set the CPU.

        Args:
            cpu: The CPU model.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.cpu = cpu
        return self

    def set_ram(self, ram: int) -> ComputerBuilder:
        """Set the RAM amount in GB.

        Args:
            ram: The RAM size in gigabytes.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.ram = ram
        return self

    def set_storage(self, storage: str) -> ComputerBuilder:
        """Set the storage configuration.

        Args:
            storage: The storage description.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.storage = storage
        return self

    def set_gpu(self, gpu: str) -> ComputerBuilder:
        """Set the GPU.

        Args:
            gpu: The GPU model.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.gpu = gpu
        return self

    def set_os(self, os: str) -> ComputerBuilder:
        """Set the operating system.

        Args:
            os: The operating system name.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.os = os
        return self

    def add_peripheral(self, peripheral: str) -> ComputerBuilder:
        """Add a peripheral device.

        Args:
            peripheral: The peripheral name.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.peripherals.append(peripheral)
        return self

    def build(self) -> Computer:
        """Build and return the configured Computer instance.

        Returns:
            The fully constructed Computer instance.
        """
        return self._computer

    def reset(self) -> ComputerBuilder:
        """Reset the builder to start building a new computer.

        Returns:
            The builder instance with a new Computer.
        """
        self._computer = Computer()
        return self

Usage

# Building a custom computer
builder = ComputerBuilder()
computer = (builder
            .set_cpu("Intel i9")
            .set_ram(32)
            .set_storage("1TB SSD")
            .set_gpu("NVIDIA RTX 4090")
            .set_os("Windows 11")
            .add_peripheral("Mechanical Keyboard")
            .add_peripheral("Gaming Mouse")
            .build())

print(computer.get_specifications())
# Output:
# CPU: Intel i9
# RAM: 32GB
# Storage: 1TB SSD
# GPU: NVIDIA RTX 4090
# OS: Windows 11
# Peripherals: Mechanical Keyboard, Gaming Mouse

Trade-offs

Benefits:

  1. Readable code through fluent interface that is self-documenting
  2. Step-by-step construction of complex objects incrementally
  3. Same builder can create different product variants
  4. Can construct immutable objects piece by piece

Drawbacks:

  1. Adds extra classes and code, increasing complexity
  2. Builder methods may duplicate product setters
  3. Creates intermediate objects during construction
  4. Product may be in invalid state during construction

Real-World Examples

  • SQL query builders constructing complex queries
  • HTTP request builders with headers, body, parameters
  • Document builders creating documents with sections
  • Test data builders with various configurations
  • Abstract Factory
  • Composite
  • Prototype
  • Singleton
  • Fluent Interface

API Reference

design_patterns.creational.builder

Builder Pattern Module

The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations. It is particularly useful when an object requires many configuration parameters or when the construction process involves multiple steps.

Example

Building a computer with various components:

builder = ComputerBuilder()
computer = (builder
            .set_cpu("Intel i9")
            .set_ram(32)
            .set_storage("1TB SSD")
            .set_gpu("NVIDIA RTX 4090")
            .build())

print(computer.get_specifications())

Computer

Represents a computer with various components.

This is the product class that the builder constructs.

Source code in src/design_patterns/creational/builder.py
class Computer:
    """Represents a computer with various components.

    This is the product class that the builder constructs.
    """

    def __init__(self) -> None:
        """Initialize an empty computer."""
        self.cpu: str | None = None
        self.ram: int | None = None
        self.storage: str | None = None
        self.gpu: str | None = None
        self.os: str | None = None
        self.peripherals: list[str] = []

    def get_specifications(self) -> str:
        """Get the computer specifications as a formatted string.

        Returns:
            A string representation of the computer specifications.
        """
        specs = []
        if self.cpu:
            specs.append(f"CPU: {self.cpu}")
        if self.ram:
            specs.append(f"RAM: {self.ram}GB")
        if self.storage:
            specs.append(f"Storage: {self.storage}")
        if self.gpu:
            specs.append(f"GPU: {self.gpu}")
        if self.os:
            specs.append(f"OS: {self.os}")
        if self.peripherals:
            specs.append(f"Peripherals: {', '.join(self.peripherals)}")
        return "\n".join(specs) if specs else "No specifications set"

__init__()

Initialize an empty computer.

Source code in src/design_patterns/creational/builder.py
def __init__(self) -> None:
    """Initialize an empty computer."""
    self.cpu: str | None = None
    self.ram: int | None = None
    self.storage: str | None = None
    self.gpu: str | None = None
    self.os: str | None = None
    self.peripherals: list[str] = []

get_specifications()

Get the computer specifications as a formatted string.

Returns:

Type Description
str

A string representation of the computer specifications.

Source code in src/design_patterns/creational/builder.py
def get_specifications(self) -> str:
    """Get the computer specifications as a formatted string.

    Returns:
        A string representation of the computer specifications.
    """
    specs = []
    if self.cpu:
        specs.append(f"CPU: {self.cpu}")
    if self.ram:
        specs.append(f"RAM: {self.ram}GB")
    if self.storage:
        specs.append(f"Storage: {self.storage}")
    if self.gpu:
        specs.append(f"GPU: {self.gpu}")
    if self.os:
        specs.append(f"OS: {self.os}")
    if self.peripherals:
        specs.append(f"Peripherals: {', '.join(self.peripherals)}")
    return "\n".join(specs) if specs else "No specifications set"

ComputerBuilder

Builder for constructing Computer objects.

This builder uses method chaining (fluent interface) to set component properties.

Source code in src/design_patterns/creational/builder.py
class ComputerBuilder:
    """Builder for constructing Computer objects.

    This builder uses method chaining (fluent interface) to set component properties.
    """

    def __init__(self) -> None:
        """Initialize the builder with a new Computer instance."""
        self._computer = Computer()

    def set_cpu(self, cpu: str) -> ComputerBuilder:
        """Set the CPU.

        Args:
            cpu: The CPU model.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.cpu = cpu
        return self

    def set_ram(self, ram: int) -> ComputerBuilder:
        """Set the RAM amount in GB.

        Args:
            ram: The RAM size in gigabytes.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.ram = ram
        return self

    def set_storage(self, storage: str) -> ComputerBuilder:
        """Set the storage configuration.

        Args:
            storage: The storage description.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.storage = storage
        return self

    def set_gpu(self, gpu: str) -> ComputerBuilder:
        """Set the GPU.

        Args:
            gpu: The GPU model.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.gpu = gpu
        return self

    def set_os(self, os: str) -> ComputerBuilder:
        """Set the operating system.

        Args:
            os: The operating system name.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.os = os
        return self

    def add_peripheral(self, peripheral: str) -> ComputerBuilder:
        """Add a peripheral device.

        Args:
            peripheral: The peripheral name.

        Returns:
            The builder instance for method chaining.
        """
        self._computer.peripherals.append(peripheral)
        return self

    def build(self) -> Computer:
        """Build and return the configured Computer instance.

        Returns:
            The fully constructed Computer instance.
        """
        return self._computer

    def reset(self) -> ComputerBuilder:
        """Reset the builder to start building a new computer.

        Returns:
            The builder instance with a new Computer.
        """
        self._computer = Computer()
        return self

__init__()

Initialize the builder with a new Computer instance.

Source code in src/design_patterns/creational/builder.py
def __init__(self) -> None:
    """Initialize the builder with a new Computer instance."""
    self._computer = Computer()

add_peripheral(peripheral)

Add a peripheral device.

Parameters:

Name Type Description Default
peripheral str

The peripheral name.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def add_peripheral(self, peripheral: str) -> ComputerBuilder:
    """Add a peripheral device.

    Args:
        peripheral: The peripheral name.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.peripherals.append(peripheral)
    return self

build()

Build and return the configured Computer instance.

Returns:

Type Description
Computer

The fully constructed Computer instance.

Source code in src/design_patterns/creational/builder.py
def build(self) -> Computer:
    """Build and return the configured Computer instance.

    Returns:
        The fully constructed Computer instance.
    """
    return self._computer

reset()

Reset the builder to start building a new computer.

Returns:

Type Description
ComputerBuilder

The builder instance with a new Computer.

Source code in src/design_patterns/creational/builder.py
def reset(self) -> ComputerBuilder:
    """Reset the builder to start building a new computer.

    Returns:
        The builder instance with a new Computer.
    """
    self._computer = Computer()
    return self

set_cpu(cpu)

Set the CPU.

Parameters:

Name Type Description Default
cpu str

The CPU model.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_cpu(self, cpu: str) -> ComputerBuilder:
    """Set the CPU.

    Args:
        cpu: The CPU model.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.cpu = cpu
    return self

set_gpu(gpu)

Set the GPU.

Parameters:

Name Type Description Default
gpu str

The GPU model.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_gpu(self, gpu: str) -> ComputerBuilder:
    """Set the GPU.

    Args:
        gpu: The GPU model.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.gpu = gpu
    return self

set_os(os)

Set the operating system.

Parameters:

Name Type Description Default
os str

The operating system name.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_os(self, os: str) -> ComputerBuilder:
    """Set the operating system.

    Args:
        os: The operating system name.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.os = os
    return self

set_ram(ram)

Set the RAM amount in GB.

Parameters:

Name Type Description Default
ram int

The RAM size in gigabytes.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_ram(self, ram: int) -> ComputerBuilder:
    """Set the RAM amount in GB.

    Args:
        ram: The RAM size in gigabytes.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.ram = ram
    return self

set_storage(storage)

Set the storage configuration.

Parameters:

Name Type Description Default
storage str

The storage description.

required

Returns:

Type Description
ComputerBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_storage(self, storage: str) -> ComputerBuilder:
    """Set the storage configuration.

    Args:
        storage: The storage description.

    Returns:
        The builder instance for method chaining.
    """
    self._computer.storage = storage
    return self

House

Represents a house with various features.

This demonstrates an alternative product for the builder pattern.

Source code in src/design_patterns/creational/builder.py
class House:
    """Represents a house with various features.

    This demonstrates an alternative product for the builder pattern.
    """

    def __init__(self) -> None:
        """Initialize an empty house."""
        self.foundation: str | None = None
        self.walls: str | None = None
        self.roof: str | None = None
        self.windows: int = 0
        self.doors: int = 0
        self.garage: bool = False
        self.garden: bool = False

    def describe(self) -> str:
        """Get a description of the house.

        Returns:
            A string describing the house features.
        """
        features = []
        if self.foundation:
            features.append(f"Foundation: {self.foundation}")
        if self.walls:
            features.append(f"Walls: {self.walls}")
        if self.roof:
            features.append(f"Roof: {self.roof}")
        features.append(f"Windows: {self.windows}")
        features.append(f"Doors: {self.doors}")
        if self.garage:
            features.append("Has garage")
        if self.garden:
            features.append("Has garden")
        return ", ".join(features) if features else "Empty house"

__init__()

Initialize an empty house.

Source code in src/design_patterns/creational/builder.py
def __init__(self) -> None:
    """Initialize an empty house."""
    self.foundation: str | None = None
    self.walls: str | None = None
    self.roof: str | None = None
    self.windows: int = 0
    self.doors: int = 0
    self.garage: bool = False
    self.garden: bool = False

describe()

Get a description of the house.

Returns:

Type Description
str

A string describing the house features.

Source code in src/design_patterns/creational/builder.py
def describe(self) -> str:
    """Get a description of the house.

    Returns:
        A string describing the house features.
    """
    features = []
    if self.foundation:
        features.append(f"Foundation: {self.foundation}")
    if self.walls:
        features.append(f"Walls: {self.walls}")
    if self.roof:
        features.append(f"Roof: {self.roof}")
    features.append(f"Windows: {self.windows}")
    features.append(f"Doors: {self.doors}")
    if self.garage:
        features.append("Has garage")
    if self.garden:
        features.append("Has garden")
    return ", ".join(features) if features else "Empty house"

HouseBuilder

Builder for constructing House objects.

This demonstrates director methods that encapsulate common build configurations.

Source code in src/design_patterns/creational/builder.py
class HouseBuilder:
    """Builder for constructing House objects.

    This demonstrates director methods that encapsulate common build configurations.
    """

    def __init__(self) -> None:
        """Initialize the builder with a new House instance."""
        self._house = House()

    def set_foundation(self, foundation: str) -> HouseBuilder:
        """Set the foundation type.

        Args:
            foundation: The foundation type.

        Returns:
            The builder instance for method chaining.
        """
        self._house.foundation = foundation
        return self

    def set_walls(self, walls: str) -> HouseBuilder:
        """Set the wall material.

        Args:
            walls: The wall material.

        Returns:
            The builder instance for method chaining.
        """
        self._house.walls = walls
        return self

    def set_roof(self, roof: str) -> HouseBuilder:
        """Set the roof type.

        Args:
            roof: The roof type.

        Returns:
            The builder instance for method chaining.
        """
        self._house.roof = roof
        return self

    def set_windows(self, count: int) -> HouseBuilder:
        """Set the number of windows.

        Args:
            count: Number of windows.

        Returns:
            The builder instance for method chaining.
        """
        self._house.windows = count
        return self

    def set_doors(self, count: int) -> HouseBuilder:
        """Set the number of doors.

        Args:
            count: Number of doors.

        Returns:
            The builder instance for method chaining.
        """
        self._house.doors = count
        return self

    def add_garage(self) -> HouseBuilder:
        """Add a garage to the house.

        Returns:
            The builder instance for method chaining.
        """
        self._house.garage = True
        return self

    def add_garden(self) -> HouseBuilder:
        """Add a garden to the house.

        Returns:
            The builder instance for method chaining.
        """
        self._house.garden = True
        return self

    def build(self) -> House:
        """Build and return the configured House instance.

        Returns:
            The fully constructed House instance.
        """
        return self._house

    def build_simple_house(self) -> House:
        """Build a simple house with basic features.

        This is a director method that encapsulates a common configuration.

        Returns:
            A simple house.
        """
        return (self
                .set_foundation("Concrete slab")
                .set_walls("Brick")
                .set_roof("Asphalt shingles")
                .set_windows(4)
                .set_doors(1)
                .build())

    def build_luxury_house(self) -> House:
        """Build a luxury house with premium features.

        This is a director method that encapsulates a premium configuration.

        Returns:
            A luxury house.
        """
        return (self
                .set_foundation("Deep foundation")
                .set_walls("Stone")
                .set_roof("Tile")
                .set_windows(12)
                .set_doors(3)
                .add_garage()
                .add_garden()
                .build())

__init__()

Initialize the builder with a new House instance.

Source code in src/design_patterns/creational/builder.py
def __init__(self) -> None:
    """Initialize the builder with a new House instance."""
    self._house = House()

add_garage()

Add a garage to the house.

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def add_garage(self) -> HouseBuilder:
    """Add a garage to the house.

    Returns:
        The builder instance for method chaining.
    """
    self._house.garage = True
    return self

add_garden()

Add a garden to the house.

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def add_garden(self) -> HouseBuilder:
    """Add a garden to the house.

    Returns:
        The builder instance for method chaining.
    """
    self._house.garden = True
    return self

build()

Build and return the configured House instance.

Returns:

Type Description
House

The fully constructed House instance.

Source code in src/design_patterns/creational/builder.py
def build(self) -> House:
    """Build and return the configured House instance.

    Returns:
        The fully constructed House instance.
    """
    return self._house

build_luxury_house()

Build a luxury house with premium features.

This is a director method that encapsulates a premium configuration.

Returns:

Type Description
House

A luxury house.

Source code in src/design_patterns/creational/builder.py
def build_luxury_house(self) -> House:
    """Build a luxury house with premium features.

    This is a director method that encapsulates a premium configuration.

    Returns:
        A luxury house.
    """
    return (self
            .set_foundation("Deep foundation")
            .set_walls("Stone")
            .set_roof("Tile")
            .set_windows(12)
            .set_doors(3)
            .add_garage()
            .add_garden()
            .build())

build_simple_house()

Build a simple house with basic features.

This is a director method that encapsulates a common configuration.

Returns:

Type Description
House

A simple house.

Source code in src/design_patterns/creational/builder.py
def build_simple_house(self) -> House:
    """Build a simple house with basic features.

    This is a director method that encapsulates a common configuration.

    Returns:
        A simple house.
    """
    return (self
            .set_foundation("Concrete slab")
            .set_walls("Brick")
            .set_roof("Asphalt shingles")
            .set_windows(4)
            .set_doors(1)
            .build())

set_doors(count)

Set the number of doors.

Parameters:

Name Type Description Default
count int

Number of doors.

required

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_doors(self, count: int) -> HouseBuilder:
    """Set the number of doors.

    Args:
        count: Number of doors.

    Returns:
        The builder instance for method chaining.
    """
    self._house.doors = count
    return self

set_foundation(foundation)

Set the foundation type.

Parameters:

Name Type Description Default
foundation str

The foundation type.

required

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_foundation(self, foundation: str) -> HouseBuilder:
    """Set the foundation type.

    Args:
        foundation: The foundation type.

    Returns:
        The builder instance for method chaining.
    """
    self._house.foundation = foundation
    return self

set_roof(roof)

Set the roof type.

Parameters:

Name Type Description Default
roof str

The roof type.

required

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_roof(self, roof: str) -> HouseBuilder:
    """Set the roof type.

    Args:
        roof: The roof type.

    Returns:
        The builder instance for method chaining.
    """
    self._house.roof = roof
    return self

set_walls(walls)

Set the wall material.

Parameters:

Name Type Description Default
walls str

The wall material.

required

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_walls(self, walls: str) -> HouseBuilder:
    """Set the wall material.

    Args:
        walls: The wall material.

    Returns:
        The builder instance for method chaining.
    """
    self._house.walls = walls
    return self

set_windows(count)

Set the number of windows.

Parameters:

Name Type Description Default
count int

Number of windows.

required

Returns:

Type Description
HouseBuilder

The builder instance for method chaining.

Source code in src/design_patterns/creational/builder.py
def set_windows(self, count: int) -> HouseBuilder:
    """Set the number of windows.

    Args:
        count: Number of windows.

    Returns:
        The builder instance for method chaining.
    """
    self._house.windows = count
    return self