THN Interview Prep

Builder (Creational)

Intent / problem it solves

Separate construction of a complex object from its representation, allowing step-by-step assembly and varying configurations (required vs optional fields, fluent APIs).

When to use / when NOT

Use when many optional parameters exist, invariants span multiple fields, or you want readable construction (fluent builder).

Avoid when a constructor or small factory covers all cases, or when immutability plus a plain struct literal is enough.

Structure

Director (optional) orchestrates builder steps; concrete builders accumulate state and return the product.

Loading diagram…

Go example

package main

import "fmt"

type Query struct {
	table   string
	columns []string
	limit   int
}

type QueryBuilder struct{ query Query }

func NewQueryBuilder() *QueryBuilder { return &QueryBuilder{} }

func (builder *QueryBuilder) From(table string) *QueryBuilder {
	builder.query.table = table
	return builder
}

func (builder *QueryBuilder) Select(columns ...string) *QueryBuilder {
	builder.query.columns = columns
	return builder
}

func (builder *QueryBuilder) Limit(limit int) *QueryBuilder {
	builder.query.limit = limit
	return builder
}

func (builder *QueryBuilder) Build() Query { return builder.query }

func main() {
	query := NewQueryBuilder().From("orders").Select("id", "total").Limit(10).Build()
	fmt.Println(query)
}

JavaScript example

class HttpRequest {
  constructor({ method, url, headers, body }) {
    this.method = method;
    this.url = url;
    this.headers = headers;
    this.body = body;
  }
}

class HttpRequestBuilder {
  constructor() {
    this.method = 'GET';
    this.url = '';
    this.headers = {};
    this.body = null;
  }

  setMethod(method) {
    this.method = method;
    return this;
  }

  setUrl(url) {
    this.url = url;
    return this;
  }

  setHeader(name, value) {
    this.headers[name] = value;
    return this;
  }

  setBody(body) {
    this.body = body;
    return this;
  }

  build() {
    return new HttpRequest({
      method: this.method,
      url: this.url,
      headers: { ...this.headers },
      body: this.body,
    });
  }
}

const request = new HttpRequestBuilder()
  .setMethod('POST')
  .setUrl('/api/orders')
  .setHeader('content-type', 'application/json')
  .setBody({ amount: 42 })
  .build();

console.log(request.method, request.body);

Interview phrase

“Builder keeps complex construction readable and validates invariants before returning the object; I use it for requests, configs, and test data where optional fields explode.”

Map to LLD for request builders, report pipelines, or menu / DSL construction in LLD case studies.

Last updated on

Spotted something unclear or wrong on this page?

On this page