Builder Design Pattern

Last Updated : 12 Feb, 2026

The Builder Design Pattern is a creational design pattern that provides a step-by-step approach to constructing complex objects. It separates the construction process from the object’s representation, enabling the same method to create different variations of an object.

  • Encapsulates object construction logic in a separate Builder class.
  • Allows flexible and controlled object creation.
  • Supports different variations of a product using the same process.
  • Improves readability and maintainability by avoiding long constructors with many parameters.

Features

The Builder pattern focuses on constructing complex objects in a controlled and step-by-step manner.

  • Constructs complex objects step by step
  • Separates construction logic from the final object representation
  • Uses a Builder class to control object creation
  • Supports creation of different variations of the same object
  • May include a Director class to define the construction sequence

Uses

The Builder Pattern is helpful when creating complex objects with multiple optional steps or configurations.

  • Useful for complex objects with many optional steps.
  • Separates construction logic from object representation.
  • Avoids telescoping constructors with too many parameters.
  • Supports creating different representations using the same construction process.

Components

The Builder Pattern consists of several key components that work together to construct complex objects step by step while keeping construction separate from representation.

  • Product: The Product is the complex object that the Builder pattern is responsible for constructing.
  • Builder: An interface/abstract class that defines steps for building parts of the product.
  • Concrete Builder: Implements the Builder interface with specific logic to build a variation of the product.
  • Director: Manages the building process and defines the order of construction.
  • Client: Initiates the building process and requests the final product.

Implementation

Below are the steps to implement the Builder Design Pattern:

  1. Create the Product Class: Define the object (product) that will be built. This class contains all the fields that make up the object.
  2. Create the Builder Class: This class will have methods to set the different parts of the product. Each method returns the builder itself to allow method chaining.
  3. Add a Build Method: In the builder class, add a method called build() (or similar) that assembles the product and returns the final object.
  4. Use the Director (Optional): If needed, you can create a director class to control the building process and decide the order in which parts are constructed.
  5. Client Uses the Builder: The client will use the builder to set the desired parts step by step and call the build() method to get the final product.

Let’s start by understanding the Builder Design Pattern in a simple and beginner-friendly way.

Problem Statement

  • You need to implement a system for building custom computers with different configurations of CPU, RAM and storage.
  • The goal is to allow flexibility in creating multiple variations of computers through a step-by-step construction process.
uml_class_diagram_for_builder_design_pattern
UML Diagram

1. Product (Computer)

The final complex object that is created using the Builder pattern.

C++
// Product
class Computer {
 
private:
    string cpu_;
    string ram_;
    string storage_;
  
  
public:
    void setCPU(const std::string& cpu) {
        cpu_ = cpu;
    }

    void setRAM(const std::string& ram) {
        ram_ = ram;
    }

    void setStorage(const std::string& storage) {
        storage_ = storage;
    }

    void displayInfo() const {
        std::cout << "Computer Configuration:"
                  << "\nCPU: " << cpu_
                  << "\nRAM: " << ram_
                  << "\nStorage: " << storage_ << "\n\n";
    }
};
Java
/* Product */
class Computer {

    private String cpu_;
    private String ram_;
    private String storage_;

    public void setCPU(String cpu) {
        cpu_ = cpu;
    }

    public void setRAM(String ram) {
        ram_ = ram;
    }

    public void setStorage(String storage) {
        storage_ = storage;
    }

    public void displayInfo() {
        System.out.println("Computer Configuration:"
                + "\nCPU: " + cpu_
                + "\nRAM: " + ram_
                + "\nStorage: " + storage_ + "\n\n");
    }
}
Python
""" Product """
class Computer:

    def __init__(self):
        self.cpu_ = ""
        self.ram_ = ""
        self.storage_ = ""

    def setCPU(self, cpu):
        self.cpu_ = cpu

    def setRAM(self, ram):
        self.ram_ = ram

    def setStorage(self, storage):
        self.storage_ = storage

    def displayInfo(self):
        print(f'Computer Configuration:\nCPU: {self.cpu_}\nRAM: {self.ram_}\nStorage: {self.storage_}\n\n')
JavaScript
/* Product */
class Computer {

    constructor() {
        this.cpu_ = "";
        this.ram_ = "";
        this.storage_ = "";
    }

    setCPU(cpu) {
        this.cpu_ = cpu;
    }

    setRAM(ram) {
        this.ram_ = ram;
    }

    setStorage(storage) {
        this.storage_ = storage;
    }

    displayInfo() {
        console.log(`Computer Configuration:\nCPU: ${this.cpu_}\nRAM: ${this.ram_}\nStorage: ${this.storage_}\n\n`);
    }
}

2. Builder

An interface/abstract class that defines step-by-step methods to create different parts of the Product (Computer).

C++
// Builder interface
class Builder {
public:
    virtual void buildCPU() = 0;
    virtual void buildRAM() = 0;
    virtual void buildStorage() = 0;
    virtual Computer getResult() = 0;
};
Java
/* Builder interface */
interface Builder {
    void buildCPU();
    void buildRAM();
    void buildStorage();
    Computer getResult();
}
Python
""" Builder interface """
from abc import ABC, abstractmethod

class Builder(ABC):
    @abstractmethod
    def buildCPU(self):
        pass

    @abstractmethod
    def buildRAM(self):
        pass

    @abstractmethod
    def buildStorage(self):
        pass

    @abstractmethod
    def getResult(self):
        pass
JavaScript
/* Builder interface */
class Builder {
    buildCPU() {
        throw new Error("Method not implemented.");
    }

    buildRAM() {
        throw new Error("Method not implemented.");
    }

    buildStorage() {
        throw new Error("Method not implemented.");
    }

    getResult() {
        throw new Error("Method not implemented.");
    }
}

3. Concrete Builder (Gaming Computer Builder)

A specific builder class that implements the Builder steps to create a gaming computer configuration.

C++
// Builder interface
class ConcreteBuilder {
public:
    virtual void buildCPU() = 0;
    virtual void buildRAM() = 0;
    virtual void buildStorage() = 0;
    virtual Computer getResult() = 0;
};
Java
public interface ConcreteBuilder {
    void buildCPU();
    void buildRAM();
    void buildStorage();
    Computer getResult();
}
Python
from abc import ABC, abstractmethod

class ConcreteBuilder(ABC):
    @abstractmethod
    def build_cpu(self):
        pass

    @abstractmethod
    def build_ram(self):
        pass

    @abstractmethod
    def build_storage(self):
        pass

    @abstractmethod
    def get_result(self):
        pass
JavaScript
class ConcreteBuilder {
    buildCPU() {
        throw new Error("Method not implemented.");
    }

    buildRAM() {
        throw new Error("Method not implemented.");
    }

    buildStorage() {
        throw new Error("Method not implemented.");
    }

    getResult() {
        throw new Error("Method not implemented.");
    }
}

4. Director

A class that controls the building process by calling builder methods in the correct order to construct the product.

C++
// Director
class ComputerDirector {
public:
    void construct(Builder& builder) {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
};
Java
/* Director */
public class ComputerDirector {
    public void construct(Builder builder) {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
}
Python
""" Director """
class ComputerDirector:
    def __init__(self):
        pass
    def construct(self, builder):
        builder.buildCPU()
        builder.buildRAM()
        builder.buildStorage()
JavaScript
/* Director */
class ComputerDirector {
    constructor() {}
    construct(builder) {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
}

5. Client

The user/code that selects a builder, starts the building process, and finally gets the completed product.

C++
// Client
int main() {
    GamingComputerBuilder gamingBuilder;
    ComputerDirector director;

    director.construct(gamingBuilder);
    Computer gamingComputer = gamingBuilder.getResult();

    gamingComputer.displayInfo();

    return 0;
}
Java
/* Client */
public class Main {
    public static void main(String[] args) {
        GamingComputerBuilder gamingBuilder = new GamingComputerBuilder();
        ComputerDirector director = new ComputerDirector();

        director.construct(gamingBuilder);
        Computer gamingComputer = gamingBuilder.getResult();

        gamingComputer.displayInfo();
    }
}

class GamingComputerBuilder {
    public void construct() {
        // Implementation
    }
    public Computer getResult() {
        return new Computer();
    }
}

class ComputerDirector {
    public void construct(GamingComputerBuilder builder) {
        builder.construct();
    }
}

class Computer {
    public void displayInfo() {
        System.out.println("Displaying computer info");
    }
}
Python
''' Client '''

class GamingComputerBuilder:
    def construct(self):
        # Implementation
        pass

    def get_result(self):
        return Computer()

class ComputerDirector:
    def construct(self, builder):
        builder.construct()

class Computer:
    def display_info(self):
        print('Displaying computer info')

def main():
    gaming_builder = GamingComputerBuilder()
    director = ComputerDirector()

    director.construct(gaming_builder)
    gaming_computer = gaming_builder.get_result()

    gaming_computer.display_info()

if __name__ == "__main__":
    main()
JavaScript
/* Client */
class GamingComputerBuilder {
    construct() {
        // Implementation
    }
    getResult() {
        return new Computer();
    }
}

class ComputerDirector {
    construct(builder) {
        builder.construct();
    }
}

class Computer {
    displayInfo() {
        console.log('Displaying computer info');
    }
}

function main() {
    const gamingBuilder = new GamingComputerBuilder();
    const director = new ComputerDirector();

    director.construct(gamingBuilder);
    const gamingComputer = gamingBuilder.getResult();

    gamingComputer.displayInfo();
}

main();

Complete Combined code for the above example

C++
#include <iostream>
#include <string>

using namespace std;

// Product
class Computer
{
  public:
    void setCPU(const std::string &cpu)
    {
        cpu_ = cpu;
    }

    void setRAM(const std::string &ram)
    {
        ram_ = ram;
    }

    void setStorage(const std::string &storage)
    {
        storage_ = storage;
    }

    void displayInfo() const
    {
        std::cout << "Computer Configuration:"
                  << "\nCPU: " << cpu_ << "\nRAM: " << ram_ << "\nStorage: " << storage_ << "\n\n";
    }

  private:
    string cpu_;
    string ram_;
    string storage_;
};

// Builder interface
class Builder
{
  public:
    virtual void buildCPU() = 0;
    virtual void buildRAM() = 0;
    virtual void buildStorage() = 0;
    virtual Computer getResult() = 0;
};

// ConcreteBuilder
class GamingComputerBuilder : public Builder
{
  private:
    Computer computer_;

  public:
    void buildCPU() override
    {
        computer_.setCPU("Gaming CPU");
    }

    void buildRAM() override
    {
        computer_.setRAM("16GB DDR4");
    }

    void buildStorage() override
    {
        computer_.setStorage("1TB SSD");
    }

    Computer getResult() override
    {
        return computer_;
    }
};

// Director
class ComputerDirector
{
  public:
    void construct(Builder &builder)
    {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
};

// Client
int main()
{
    GamingComputerBuilder gamingBuilder;
    ComputerDirector director;

    director.construct(gamingBuilder);
    Computer gamingComputer = gamingBuilder.getResult();

    gamingComputer.displayInfo();

    return 0;
}
Java
import java.util.ArrayList;

// Product
class Computer {
    private String cpu;
    private String ram;
    private String storage;

    public void setCPU(String cpu) { this.cpu = cpu; }

    public void setRAM(String ram) { this.ram = ram; }

    public void setStorage(String storage)
    {
        this.storage = storage;
    }

    public void displayInfo()
    {
        System.out.println("Computer Configuration:\n"
                           + "CPU: " + cpu + "\n"
                           + "RAM: " + ram + "\n"
                           + "Storage: " + storage + "\n");
    }
}

// Builder interface
interface Builder {
    void buildCPU();
    void buildRAM();
    void buildStorage();
    Computer getResult();
}

// ConcreteBuilder
class GamingComputerBuilder implements Builder {
    private Computer computer = new Computer();

    public void buildCPU()
    {
        computer.setCPU("Gaming CPU");
    }

    public void buildRAM() { computer.setRAM("16GB DDR4"); }

    public void buildStorage()
    {
        computer.setStorage("1TB SSD");
    }

    public Computer getResult() { return computer; }
}

// Director
class ComputerDirector {
    public void construct(Builder builder)
    {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
}

// Client
public class Main {
    public static void main(String[] args)
    {
        GamingComputerBuilder gamingBuilder
            = new GamingComputerBuilder();
        ComputerDirector director = new ComputerDirector();

        director.construct(gamingBuilder);
        Computer gamingComputer = gamingBuilder.getResult();

        gamingComputer.displayInfo();
    }
}
Python
class Computer:
    def __init__(self):
        self.cpu = None
        self.ram = None
        self.storage = None

    def set_cpu(self, cpu):
        self.cpu = cpu

    def set_ram(self, ram):
        self.ram = ram

    def set_storage(self, storage):
        self.storage = storage

    def display_info(self):
        print(
            f'Computer Configuration:\nCPU: {self.cpu}\nRAM: {self.ram}\nStorage: {self.storage}\n')

# Builder interface
class Builder:
    def build_cpu(self):
        pass

    def build_ram(self):
        pass

    def build_storage(self):
        pass

    def get_result(self):
        pass

# ConcreteBuilder


class GamingComputerBuilder(Builder):
    def __init__(self):
        self.computer = Computer()

    def build_cpu(self):
        self.computer.set_cpu('Gaming CPU')

    def build_ram(self):
        self.computer.set_ram('16GB DDR4')

    def build_storage(self):
        self.computer.set_storage('1TB SSD')

    def get_result(self):
        return self.computer

# Director


class ComputerDirector:
    def construct(self, builder):
        builder.build_cpu()
        builder.build_ram()
        builder.build_storage()


# Client
if __name__ == '__main__':
    gaming_builder = GamingComputerBuilder()
    director = ComputerDirector()

    director.construct(gaming_builder)
    gaming_computer = gaming_builder.get_result()

    gaming_computer.display_info()
JavaScript
class Computer {
    constructor()
    {
        this.cpu = null;
        this.ram = null;
        this.storage = null;
    }

    setCPU(cpu) { this.cpu = cpu; }

    setRAM(ram) { this.ram = ram; }

    setStorage(storage) { this.storage = storage; }

    displayInfo()
    {
        console.log(`Computer Configuration:\nCPU: ${
            this.cpu}\nRAM: ${this.ram}\nStorage: ${
            this.storage}\n`);
    }
}

// Builder interface
class Builder {
    buildCPU() {}
    buildRAM() {}
    buildStorage() {}
    getResult() {}
}

// ConcreteBuilder
class GamingComputerBuilder extends Builder {
    constructor()
    {
        super();
        this.computer = new Computer();
    }

    buildCPU() { this.computer.setCPU("Gaming CPU"); }

    buildRAM() { this.computer.setRAM("16GB DDR4"); }

    buildStorage() { this.computer.setStorage("1TB SSD"); }

    getResult() { return this.computer; }
}

// Director
class ComputerDirector {
    construct(builder)
    {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
    }
}

// Client
const gamingBuilder = new GamingComputerBuilder();
const director = new ComputerDirector();

director.construct(gamingBuilder);
const gamingComputer = gamingBuilder.getResult();

gamingComputer.displayInfo();

Output
Computer Configuration:
CPU: Gaming CPU
RAM: 16GB DDR4
Storage: 1TB SSD
  • The Computer class represents the final product being built.
  • GamingComputerBuilder implements the Builder interface to define how each part of the Computer is created.
  • ComputerDirector controls the building process, while the client uses the builder and director to assemble the product.

Real-Life Software Applications

The Builder Pattern is widely used in real-life software applications to construct complex objects step by step.

  • SQL Query Builders: Used in ORMs (like Hibernate, SQLAlchemy, Laravel’s Eloquent) to dynamically construct SQL queries with methods like select(), where(), orderBy(), etc.
  • UI Component Builders: Useful in building dialog boxes, forms or widgets step by step by adding buttons, text fields or styles.
  • Document Builders: Used in tools like PDF/HTML generators, where content and styles are added step by step.

Advantages

The Builder pattern improves flexibility and readability when creating complex objects.

  • Improves readability by avoiding constructors with many parameters
  • Provides better control over object creation
  • Promotes immutability by allowing the final object to be immutable
  • Makes code more maintainable and flexible
  • Supports different representations of a product using the same building process

Disadvantages

Although powerful, the Builder pattern can introduce additional structure and complexity.

  • Increases the number of classes in the system
  • Adds unnecessary complexity for simple objects
  • Requires changes if the product structure changes significantly
  • More verbose compared to simple constructors
Comment

Explore