BuildBot

Patterns That Matter

Factory & builder

Lesson 4 of 5

What you'll learn

  • Use a factory function to centralize object construction and avoid scattered new calls.
  • Use a builder for fluent, step-by-step configuration of complex objects.
  • Know when an options object beats both.

Factory: one place that knows how to build

A factory centralizes construction so the rest of your code asks for a thing without knowing how it is assembled. In TypeScript this is almost always a plain function, not an abstract factory class hierarchy.

type Client = { baseUrl: string; headers: Record<string, string> };

// A factory function — one place that knows the assembly rules.
function createClient(env: "dev" | "prod"): Client {
  const baseUrl = env === "prod" ? "https://api.app.com" : "http://localhost:3000";
  return { baseUrl, headers: { "x-env": env } };
}

The value is centralization: change how clients are built in one spot. You rarely need the GoF abstract-factory layering unless you are swapping whole product families at runtime, which most apps never do.

Builder: fluent step-by-step config

A builder shines when an object has many optional parts and you want to assemble it incrementally and readably. Each method returns the builder, so calls chain.

class QueryBuilder {
  private parts: { table?: string; where: string[]; limit?: number } = { where: [] };
  from(table: string) {
    this.parts.table = table;
    return this;
  }
  where(clause: string) {
    this.parts.where.push(clause);
    return this;
  }
  take(n: number) {
    this.parts.limit = n;
    return this;
  }
  build() {
    return this.parts;
  }
}

A builder earns its keep when there is ordering, validation between steps, or a genuinely large surface. For three or four flat options, a single options object is simpler and just as clear — do not reach for a builder out of habit.

Options object first

Start with a plain options argument. Promote to a builder only when the config has stages, conditional steps, or accumulation. Premature builders add API surface for no benefit.

Fluent config builder

Run the builder. Chain the methods to assemble a config object step by step, then call build to get the finished plain object.

Loading editor…
Knowledge check

When is a builder worth using over a plain options object?

Saved on this device. Sign in to sync your progress everywhere.