← Back to list

Builder Design Pattern

Builder Pattern is a creational design pattern that separates the process of constructing a complex object from its representation…

Kaizen Chandra · 2026-01-19 10:22 · 0 claps · 3.9 min read
#builder-design-pattern #gang-of-four #design-patterns
Open on Medium ↗

Builder Design Pattern

Builder Design Pattern

Builder Pattern is a creational design pattern that separates the process of constructing a complex object from its representation, allowing the same construction process to create different representations of the object.

Produces different types and representation of objects using the same construction process, its extract the object construction and creation code out of it’s own class and move it to separate object called Builder.

In simple terms:

If building an object involves many steps, parameters, or conditional configurations, the Builder pattern gives you a step-by-step controlled way to create it — without the client worrying about the internal complexities.

Why Should We Use the Builder Pattern?

Here are key reasons why Builder is useful:

1. Better Handling of Complex Objects

When an object has many attributes — especially optional ones — placing them all in constructors leads to telescoping constructors (a long list of overloaded versions). This is confusing, hard to read, and hard to maintain.

2. Flexibility in Object Creation

You can construct different representations of the same object without changing the core process. For example, a “sports car” versus an “off-road car” using the same build steps but different component values.

3. Improves Readability and Maintenance

Using a fluent, method-chaining style (like builder.setX().setY().build()), code becomes easy to read and hard to misuse.

4. Order of Construction Controlled

A Builder (often directed by a Director class) controls the order of building steps, preventing clients from accidentally creating inconsistent states.

Component

Product — The complex object being built (e.g., a House).

Builder (Interface/Abstract) — Declares methods for building parts of the Product.

ConcreteBuilder — Implements the Builder steps and assembles the product.

Director (Optional) — Controls the sequence of construction steps and orchestrates the Builder.

Define the order in which we should call the construction steps so that we can reuse the configurations of the products we are building.

Hides the detail of the product construction from the client code.

Client — Uses the Director/Builder to get the final Product.

Telescoping Constructor Anti-Pattern

This happens when a class has multiple overloaded constructors to support different combinations of parameters.

public class User {
    public User(String name) { }
    public User(String name, int age) { }
    public User(String name, int age, String email) { }
    public User(String name, int age, String email, String address) { }
}

Long Parameter List Anti-Pattern

new Order(
    "ORD123",
    "John",
    "Mumbai",
    "India",
    "Express",
    true,
    false
);

A constructor or method with too many parameters, especially of the same type.

Builder replaces constructor overloads with named, fluent methods, making intent obvious:

User user = User.builder()
    .name("John")
    .age(30)
    .email("john@mail.com")
    .build();

Objects are created using a no-arg constructor and then populated via setters.

Setter-Based Construction Anti-Pattern

1. Object Can Be in an Invalid State

Nothing enforces that required fields are set.

2. Breaks Immutability

Setters make objects mutable, leading to:

  • Thread-safety issues
  • Unexpected state changes
  • Hard-to-debug bugs

3. Construction Logic Is Leaked

Clients must know how and in what order to initialize the object.

Reusability and limitations

The Builder pattern also allows for reusing existing instances, which already have been populated in a previous construction process. This makes it easy to create a new object that has only a few different attribute values, since you do not have to set all the values again.

State Validation

Builder pattern also allows for convenient state validation during the construction process of the instance

Real Time Example


public enum HttpMethod {
    GET(false),
    POST(true),
    PUT(true),
    DELETE(false);

    private final boolean allowsBody;

    HttpMethod(boolean allowsBody) {
        this.allowsBody = allowsBody;
    }

    public boolean allowsBody() {
        return allowsBody;
    }
}

import java.util.Collections;
import java.util.Map;
import java.util.Objects;

public final class HttpRequest {

    private final HttpMethod method;
    private final String url;
    private final Map<String, String> headers;
    private final String body;

    private HttpRequest(Builder builder) {
        this.method = builder.method;
        this.url = builder.url;
        this.headers = Collections.unmodifiableMap(builder.headers);
        this.body = builder.body;
    }

    public HttpMethod getMethod() {
        return method;
    }

    public String getUrl() {
        return url;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public String getBody() {
        return body;
    }

    // ================= BUILDER =================
    public static class Builder {

        private HttpMethod method;
        private String url;
        private Map<String, String> headers = new java.util.HashMap<>();
        private String body;

        private Builder(HttpMethod method) {
            this.method = Objects.requireNonNull(method, "HTTP method cannot be null");
        }

        // ---------- Factory methods ----------
        public static Builder get(String url) {
            return new Builder(HttpMethod.GET).url(url);
        }

        public static Builder post(String url) {
            return new Builder(HttpMethod.POST).url(url);
        }

        public static Builder put(String url) {
            return new Builder(HttpMethod.PUT).url(url);
        }

        public static Builder delete(String url) {
            return new Builder(HttpMethod.DELETE).url(url);
        }

        // ---------- Builder methods ----------
        private Builder url(String url) {
            this.url = Objects.requireNonNull(url, "URL cannot be null");
            return this;
        }

        public Builder header(String key, String value) {
            headers.put(
                Objects.requireNonNull(key, "Header key cannot be null"),
                Objects.requireNonNull(value, "Header value cannot be null")
            );
            return this;
        }

        public Builder body(String body) {
            if (!method.allowsBody()) {
                throw new IllegalStateException(method + " request must not have a body");
            }
            this.body = body;
            return this;
        }

        // ---------- Validation ----------
        public HttpRequest build() {
            validate();
            return new HttpRequest(this);
        }

        private void validate() {
            if (url == null || url.isBlank()) {
                throw new IllegalStateException("URL must be provided");
            }

            if (!method.allowsBody() && body != null) {
                throw new IllegalStateException(method + " request must not contain body");
            }

            if (method.allowsBody() && body == null) {
                throw new IllegalStateException(method + " request requires a body");
            }
        }
    }
}

Conclusion

The Builder Design Pattern exists because constructors and setters fail at scale.

Use Builder when:

  • Objects are complex
  • Many optional parameters exist
  • Immutability and validation matter

Avoid Builder when:

  • Objects are simple
  • Constructors are clear and sufficient

메타데이터
post_id
df60fc01cd2a
slug
builder-design-pattern-df60fc01cd2a
url
https://medium.com/@code.chandrashekhar/builder-design-pattern-df60fc01cd2a
canonical_url
https://medium.com/@code.chandrashekhar/builder-design-pattern-df60fc01cd2a
author_url
https://medium.com/@code.chandrashekhar
status
ok
fetched_at
2026-06-23 17:05:31