creational

Builder

Separate the construction of a complex object from its final representation.

Problem

creational

Constructing complex objects directly can make required steps, optional values, and validation hard to manage.

Integration notes

Builder is most useful when construction must happen in controlled steps and the final object has many optional or ordered parts.

Tradeoffs

  • Adds more classes or steps to the construction process.
  • Can be overkill for simple objects.
  • Improves clarity when object construction is complex or incremental.

Languages

typescript, python, java, react, angular, go, csharp, dotnet

Platforms

frontend, backend, integration

Variants

frontend

Staged typed builder

typescript

Use a staged builder so required steps must be completed before the final object can be created.

Intent: Enforce construction order and required fields at compile time.

Problem: Optional and required fields are easy to mix up when object creation is too flexible.

Solution: Use staged types to guide the caller through the construction steps in the correct order.

Dependencies

builder

Related variants

builder-fluent-requestbuilder-director-driven

Examples

builder

This is the best choice when the final object must never be partially built or invalid.

Scenarios

UI form assembly

A form workflow constructs a multi-step interface with fields, validation, and actions.

Context: An app needs to build forms dynamically based on user role, plan, or workflow state.

Problem: Inline form creation makes complex UI flows difficult to maintain and extend.

Solution: Use Builder to assemble the form in stages.

frontend

Language examples

Core languages

Frameworks and libraries

UI form assemblytypescript

A builder fits staged UI assembly because the form can be configured progressively based on workflow state.

TypeScript
type FormField = {
  name: string;
  label: string;
  required: boolean;
};

type FormConfig = {
  title: string;
  fields: FormField[];
  submitLabel: string;
};

class FormBuilder {
  private config: FormConfig = {
    title: "",
    fields: [],
    submitLabel: "Submit",
  };

  title(title: string) {
    this.config.title = title;
    return this;
  }

  addField(field: FormField) {
    this.config.fields.push(field);
    return this;
  }

  submitLabel(label: string) {
    this.config.submitLabel = label;
    return this;
  }

  build() {
    return this.config;
  }
}

const form = new FormBuilder()
  .title("Profile setup")
  .addField({ name: "email", label: "Email", required: true })
  .addField({ name: "timezone", label: "Timezone", required: false })
  .submitLabel("Save profile")
  .build();

Real-world examples

  • REST request builders: HTTP clients often expose builder APIs to assemble headers, query parameters, and payloads step by step.
  • Report pipelines: Reporting systems often use a builder-like assembly process to add sections, charts, and metadata in stages.
  • Form wizards: Multi-step UI flows often build up forms progressively before the final submission step.