Table of contents
1.
Introduction
2.
What Is the Builder Design Pattern?
2.1.
Key Characteristics of the Builder Pattern
2.1.1.
1. Step-by-Step Construction
2.1.2.
2. Immutability
2.1.3.
3. Method Chaining
3.
When Will We Need Builder Design Pattern?
4.
How Does Builder Design Pattern Work?
4.1.
Structure
4.1.1.
Builder
4.1.2.
Product
4.2.
Implementation
4.2.1.
Pseudocode
4.2.2.
Customer with pseudocode
5.
UML Diagram of Builder Design Pattern
6.
Code Implementation
6.1.
Java Code
6.2.
C++ Code
6.3.
Python Code
7.
Advantages of Builder Design Pattern
8.
Disadvantages of Builder Design Pattern
9.
Difference between Builder Design Pattern and Factory Design Pattern
10.
Builder vs Prototype Design Pattern in Java
10.1.
Builder Design Pattern Overview
10.2.
Prototype Design Pattern Overview
10.3.
Comparison
11.
Real-World Examples of Builder Pattern in Java
11.1.
Builder Pattern in Java Libraries
11.2.
Builder Pattern in Enterprise Applications
12.
Frequently Asked Questions
12.1.
What is the real life use case of the builder design pattern?
12.2.
What does a builder do in Java?
12.3.
How does the Builder Pattern improve code readability in Java?
12.4.
What are some libraries in Java that use the Builder Pattern?
13.
Conclusion
Last Updated: Jul 7, 2025
Medium

Builder Design Pattern

Author Rinki Deka
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

The Builder Design Pattern is a unique design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. It's useful when an object needs to be created with a lot of options and configurations. 

Builder design pattern.

The Builder Design Pattern is a creational design pattern that provides a way to construct complex objects step by step. It allows the construction of different representations of an object using the same construction process. The pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

What Is the Builder Design Pattern?

The Builder Design Pattern is a creational design pattern used to construct complex objects step by step. It separates the object construction process from its representation, allowing the same construction process to create different representations. This pattern is particularly useful when objects contain many optional parameters or require a multi-step configuration. As part of the Gang of Four (GoF) design patterns, Builder promotes cleaner and more maintainable object creation, especially when constructors become overloaded or hard to read.

Key Characteristics of the Builder Pattern

1. Step-by-Step Construction

The Builder pattern allows objects to be created in a controlled, step-by-step manner. A separate Builder class is responsible for setting individual properties, which makes the construction process more flexible and easier to understand. This is especially helpful for constructing objects that require multiple configuration steps.

2. Immutability

Once the final object is built using the build() method, it becomes immutable—its state cannot be changed. This immutability improves reliability and thread safety, especially in concurrent environments. Developers can trust that once an object is created, it remains consistent throughout its lifecycle.

3. Method Chaining

Builder classes often use method chaining (also known as a fluent interface). Each setter method returns the builder instance itself, allowing calls to be chained together in a single statement. This improves code readability and reduces the chance of forgetting to set required fields during object construction.

When Will We Need Builder Design Pattern?

The Builder Design Pattern is essential when constructing complex objects step by step. It is particularly beneficial when an object must be created with many optional components or configurations. It's also useful when a product contains a lot of data, some of which may or may not be required. The Builder Design Pattern is particularly useful in the following scenarios:

  • Complex Object Construction: When the construction of an object involves multiple steps, configurations, or optional features, and the process needs to be abstracted.
  • Variety of Object Representations: When there is a need to create different representations of an object using the same construction process. The Builder pattern allows flexibility in constructing various versions of an object.
  • Step-by-Step Construction: When the construction of an object follows a step-by-step process, and clients may need to customize or skip certain steps based on their requirements.
  • Telescoping Constructors Issue: To avoid the telescoping constructors anti-pattern, where a class has multiple constructors with different parameter combinations, leading to code that is hard to maintain and understand.
  • Product Immutability: When you want to ensure that the constructed object remains immutable once it's created. The Builder pattern allows constructing an immutable object gradually.
  • Separation of Concerns: When there is a need to separate the construction of an object from its representation, providing clear separation of concerns and improving code readability.

How Does Builder Design Pattern Work?

The Builder Pattern works by separating the construction of a complex object from its representation, allowing the same construction process to create different representations. It typically involves a 'Director' that constructs an object using the 'Builder' interface.

Structure

The structure of the Builder Pattern includes:

  • Builder: Provides an interface for creating parts of a Product object.
     
  • Concrete Builder: Implements the Builder interface and assembles the parts to construct the product.
     
  • Director: Constructs an object using the Builder interface.
     
  • Product: Represents the complex object being built.

Builder

The Builder interface declares product construction steps that are common to all types of builders.

public interface Builder {
    void buildPartA();
    void buildPartB();
    void buildPartC();
}

Product

The Product class represents the complex object that is being built. It's usually a class with multiple fields/attributes.

public class Product {
    private String partA;
    private String partB;
    private String partC;
    // Getters and setters for parts...
}

Implementation

Pseudocode

class Director {
    method construct(builder: Builder) {
        builder.buildPartA()
        builder.buildPartB()
        builder.buildPartC()
    }
}


interface Builder {
    method buildPartA()
    method buildPartB()
    method buildPartC()
    method getResult(): Product
}


class ConcreteBuilder implements Builder {
    private product: Product


    method buildPartA() {
        // implementation...
    }


    method buildPartB() {
        // implementation...
    }


    method buildPartC() {
        // implementation...
    }


    method getResult(): Product {
        return product
    }
}


class Client {
    method main() {
        director = new Director()
        builder = new ConcreteBuilder()
        director.construct(builder)
        product = builder.getResult()
    }
}


Customer with pseudocode

class Customer {
    private String name;
    private String address;
    // Other customer fields and methods...
}
Customer Builder with pseudocode


interface CustomerBuilder {
    method setName(name: String)
    method setAddress(address: String)
    method getResult(): Customer
}
Concrete Customer Builder with pseudocode


class ConcreteCustomerBuilder implements CustomerBuilder {
    private customer: Customer


    method setName(name: String) {
        customer.name = name
    }


    method setAddress(address: String) {
        customer.address = address
    }


    method getResult(): Customer {
        return customer
    }
}


Client with pseudocode

class Client {
    method main() {
        customerBuilder = new ConcreteCustomerBuilder()
        customerBuilder.setName("John Doe")
        customerBuilder.setAddress("123 Elm Street")
        customer = customerBuilder.getResult()
    }
}

Explanation

The pseudocode above illustrates the Builder Pattern's typical use. The Director class orchestrates the building process, which can be customized by passing different Builder implementations. The ConcreteBuilder class constructs and assembles parts of the product, which can be retrieved using the getResult method.

UML Diagram of Builder Design Pattern

The UML (Unified Modeling Language) diagram for the Builder Design Pattern typically includes the following elements:

  • Product: Represents the complex object being constructed.
  • Builder: Abstract interface declaring the construction steps for the product.
  • ConcreteBuilder: Implements the Builder interface, providing specific implementations for constructing parts of the product.
  • Director: Manages the construction process using a builder, orchestrating the steps required to construct the product.
UML Diagram of Builder Design Pattern

Code Implementation

Below are language-specific examples of implementing the Builder Design Pattern Java, C++, and Python for a hypothetical Car object, which can have various features and parts.

  • Java Code
  • C++ Code
  • Python Code

Java Code

import java.util.*;
public class Car {

private String engine;

private int wheels;

private String color;


// Getters and Setters

public String getEngine() { return engine; }

public void setEngine(String engine) { this.engine = engine; }

public int getWheels() { return wheels; }

public void setWheels(int wheels) { this.wheels = wheels; }

public String getColor() { return color; }

public void setColor(String color) { this.color = color; }

@Override

public String toString() {

return "Car [engine=" + engine + ", wheels=" + wheels + ", color=" + color + "]";

}

}

// The 'Builder' interface

public interface CarBuilder {

CarBuilder setEngine(String engine);

CarBuilder setWheels(int wheels);

CarBuilder setColor(String color);

Car build();

}

// The 'ConcreteBuilder' class

public class ConcreteCarBuilder implements CarBuilder {

private Car car;

public ConcreteCarBuilder() {

this.car = new Car();

}

@Override

public CarBuilder setEngine(String engine) {

car.setEngine(engine);

return this;

}

@Override

public CarBuilder setWheels(int wheels) {

car.setWheels(wheels);

return this;

}
@Override

public CarBuilder setColor(String color) {

car.setColor(color);

return this;

}




@Override

public Car build() {

return car;

}

}

// The 'Director' class

public class CarDirector {

public Car constructSportsCar(CarBuilder builder) {

return builder.setEngine("V8").setWheels(4).setColor("Red").build();

}

}

// The 'Client' class

public class Client {

public static void main(String[] args) {

CarBuilder builder = new ConcreteCarBuilder();

CarDirector director = new CarDirector();

Car car = director.constructSportsCar(builder);

System.out.println(car);

}

}
You can also try this code with Online Java Compiler
Run Code

C++ Code

#include <iostream>

#include <string>

// The 'Product' class

class Car {

private:

std::string engine;

int wheels;

std::string color;

public:

void setEngine(const std::string& eng) { engine = eng; }

void setWheels(int w) { wheels = w; }

void setColor(const std::string& col) { color = col; }

void show() {

std::cout <<"Car [ engine="<< engine <<", wheels=" << wheels<<", color=" << color<<"]"<<std::endl;
}

};

// The 'Builder' interface

class CarBuilder {

public:

virtual CarBuilder* setEngine(const std::string& engine) = 0;

virtual CarBuilder* setWheels(int wheels) = 0;

virtual CarBuilder* setColor(const std::string& color) = 0;

virtual Car* build() = 0;

};
// The 'ConcreteBuilder' class

class ConcreteCarBuilder : public CarBuilder {

private:

Car* car;

public:

ConcreteCarBuilder() { car = new Car(); }

~ConcreteCarBuilder() { delete car; }

CarBuilder* setEngine(const std::string& engine) override {

car->setEngine(engine);

return this;

}

CarBuilder* setWheels(int wheels) override {

car->setWheels(wheels);

return this;

}

CarBuilder* setColor(const std::string& color) override {

car->setColor(color);

return this;

}

Car* build() override {

return car;

}

};

// The 'Director' class

class CarDirector {

public:

Car* constructSportsCar(CarBuilder* builder) {

return builder->setEngine("V8")->setWheels(4)->setColor("Red")->build();
}

};

// The 'Client' code

int main() {

CarBuilder* builder = new ConcreteCarBuilder();

CarDirector director;

Car* car = director.constructSportsCar(builder);

car->show();

delete builder; // Clean up

delete car; // Clean up

return 0;

}
You can also try this code with Online C++ Compiler
Run Code

Python Code

# The 'Product' class

class Car:

def __init__(self):

self.engine = None

self.wheels = None

self.color = None

def __str__(self):

return f'Car [engine={self.engine}, wheels={self.wheels}, color={self.color}]'

# The 'Builder' interface

class CarBuilder:

def set_engine(self, engine):

pass

def set_wheels(self, wheels):

pass

def set_color(self, color):

pass

def build(self):

pass

# The 'ConcreteBuilder' class

class ConcreteCarBuilder(CarBuilder):

def __init__(self):

self.car = Car()

def set_engine(self, engine):

self.car.engine = engine

return self

def set_wheels(self, wheels):

self.car.wheels = wheels

return self

def set_color(self, color):

self.car.color = color

return self

def build(self):

return self.car

# The 'Director' class

class CarDirector:

@staticmethod

def construct_sports_car(builder):

return builder.set_engine('V8').set_wheels(4).set_color('Red').build()

# The 'Client' code

if __name__ == '__main__':

builder = ConcreteCarBuilder()

director = CarDirector()

car = director.construct_sports_car(builder)

print(car)
You can also try this code with Online Python Compiler
Run Code

Output 

output

Advantages of Builder Design Pattern

  • Flexibility in Object Creation: Allows for constructing objects step-by-step.
  • Immutability: Once built, objects can be made immutable without the need to have a constructor with too many parameters.
  • Readability: The final code is often more readable and understandable.

Disadvantages of Builder Design Pattern

  • Complexity: Can complicate the codebase with multiple additional classes and interfaces.
     
  • Development Time: More time-consuming to set up compared to simple constructors.

Difference between Builder Design Pattern and Factory Design Pattern

Here's a comparison of the Builder Design Pattern and the Factory Design Pattern in a tabular format:

AspectBuilder Design PatternFactory Design Pattern
PurposeCreates complex objects step by step, with the flexibility to configure them in a variety of ways.Creates objects, but abstracts the object creation process, returning instances of predefined types or classes.
Object CreationGradual construction, allows setting optional parameters, creating complex instances with custom configurations.Instantiates objects in a single step, returns fully initialized objects according to specific types or classes.
ComplexitySuitable for complex object creation, often with multiple optional parameters and configurations.Appropriate for simpler object creation, often with a single initialization process and predefined types.
Method ChainingTypically employs method chaining to set various attributes and properties during object construction.Usually doesn't involve method chaining for configuration; instead, parameters are passed directly to factory methods.
FlexibilityProvides high flexibility in configuring object properties, making it suitable for complex scenarios.Offers less flexibility compared to the Builder pattern, as it focuses on creating predefined objects.
ExamplesCommonly used in scenarios like building HTML elements, creating custom reports, or constructing complex database queries.Found in situations where multiple classes or subclasses share a common interface or when different object types need to be created from a factory.
Design ConsiderationsWell-suited for cases where object creation requires multiple steps and dynamic configurations.Appropriate for scenarios where object instantiation is straightforward and involves creating instances of predefined classes or types.

Builder vs Prototype Design Pattern in Java

Builder and Prototype are both creational design patterns, but they serve distinct purposes in Java development. Understanding the difference between builder and prototype pattern helps developers choose the most appropriate approach for object creation depending on the complexity and requirements of the use case. While Builder emphasizes clarity and step-by-step construction, Prototype focuses on speed and performance by reusing existing instances.

Builder Design Pattern Overview

The Builder Design Pattern in Java is used to construct complex objects step-by-step. It provides a clear separation between object construction and representation. This pattern is ideal when a class has many optional parameters or when multiple configurations of an object are required. It improves code readability through method chaining and results in more maintainable and testable code. The builder design pattern java example is commonly seen in APIs that involve constructing request bodies, configurations, or domain objects that require immutability.

Prototype Design Pattern Overview

The Prototype Design Pattern in Java allows creating new objects by cloning existing ones. Instead of building a new instance from scratch, it copies the structure and state of an existing object using a method like clone(). This pattern is particularly useful in performance-critical applications where object creation is expensive, such as in game development, caching, or GUI rendering. The prototype pattern reduces overhead by reusing existing instances and is valuable when the object construction logic is complex but needs to be reused often.

Comparison

FeatureBuilder PatternPrototype Pattern
PurposeStep-by-step object creationClone existing object
Object ControlFull control over constructionLimited to clone customization
Use CaseComplex, immutable objectsPerformance-focused cloning
Example UseConfig builders, request buildersCaching systems, graphic object cloning

Real-World Examples of Builder Pattern in Java

Understanding real-world examples of the Builder Pattern in Java helps bridge the gap between theory and practice. This pattern is widely adopted in both standard Java libraries and large-scale enterprise applications, offering a clean and scalable way to construct objects with many configuration options. It supports maintainable codebases and simplifies complex object creation in a fluent and readable manner.

Builder Pattern in Java Libraries

1. StringBuilder in Java

The StringBuilder class is a classic real-world example of the builder pattern. It allows developers to efficiently construct strings using method chaining like append(). Internally, it follows the builder pattern by modifying a mutable character array and returning the same instance. This enhances performance and readability when dealing with dynamic or multi-part strings.

2. @Builder in Lombok

The Lombok library provides a powerful annotation called @Builder, which auto-generates builder classes for Java objects. This is especially helpful in large enterprise applications where creating multiple constructors becomes repetitive. By annotating a class with @Builder, developers can construct POJOs with fluent, chainable methods, making the code more concise and readable without writing boilerplate code manually.

Builder Pattern in Enterprise Applications

1. Enterprise Configuration Setup

In real-world enterprise environments, the builder pattern is often used to construct configuration objects, such as database connection settings, security profiles, or application contexts. These setups usually involve optional fields, default values, and validations—making builders ideal for flexible and error-free configuration handling.

2. Object Creation in APIs or Frameworks

Many modern frameworks like Spring Boot and Hibernate utilize builder patterns for creating request or response objects. For example, the ResponseEntity builder in Spring lets you construct HTTP responses using fluent methods. This not only improves readability but also helps developers build consistent APIs with minimal errors.

Frequently Asked Questions

What is the real life use case of the builder design pattern?

The real life use case of the builder design pattern is building a complex object, like an email with optional attachments and formatting, where different configurations are needed.

What does a builder do in Java?

In Java, a builder is a design pattern used to construct and customize complex objects with a step-by-step approach.

How does the Builder Pattern improve code readability in Java?

The Builder Pattern improves code readability by allowing object creation through method chaining, making the code intuitive and concise. It eliminates the need for complex constructors with multiple parameters, enhancing clarity and reducing errors.

What are some libraries in Java that use the Builder Pattern?

Popular Java libraries that use the Builder Pattern include Lombok (with @Builder annotation), Google Guava (e.g., ImmutableList.Builder), and Apache HttpClient (e.g., HttpRequest.Builder), streamlining object creation with flexible and readable APIs.

Conclusion

The Builder Design Pattern is a powerful tool in a developer's toolkit, offering a structured approach to constructing complex objects. By understanding and implementing this pattern, developers can ensure their code remains clean, maintainable, and scalable. While it may introduce additional complexity, the benefits of readability and flexibility often outweigh the costs, especially in large-scale applications.

Live masterclass