Builder Pattern — Design Patterns

Builder memisahkan proses konstruksi object kompleks dari representasi akhirnya. Cocok saat object punya banyak parameter optional, atau proses pembuatannya ber

Builder memisahkan proses konstruksi object kompleks dari representasi akhirnya. Cocok saat object punya banyak parameter optional, atau proses pembuatannya berlangkah-langkah.

Problem yang diselesaikan:

Bayangkan class HttpRequest dengan parameter: URL, method, headers, body, timeout, retries, query, auth, signal, redirect policy. Constructor dengan 10 parameter = mimpi buruk:

new HttpRequest("/api/users", "POST", null, { q: "john" }, { Auth: "..." }, JSON.stringify(body), 5000, 3, "follow", controller.signal);
// Urutan membingungkan, parameter optional null-null terus

Builder memberikan fluent API yang jauh lebih readable dan self-documenting:

const req = new HttpRequestBuilder("/api/users")
  .method("POST")
  .query({ q: "john" })
  .header("Authorization", "...")
  .json({ name: "Ani" })
  .timeout(5000)
  .retries(3)
  .build();

Implementasi minimal:

class HttpRequest {
  constructor(config) {
    this.config = config;
  }
  send() {
    return fetch(this.config.url, this.config);
  }
}

class HttpRequestBuilder {
  constructor(url) {
    this.config = {
      url,
      method: "GET",
      headers: {},
      body: null,
      timeout: 30000,
    };
  }

  method(m)      { this.config.method = m; return this; }
  header(k, v)   { this.config.headers[k] = v; return this; }
  query(params)  { this.config.query = params; return this; }
  json(data)     {
    this.config.headers["Content-Type"] = "application/json";
    this.config.body = JSON.stringify(data);
    return this;
  }
  timeout(ms)    { this.config.timeout = ms; return this; }
  retries(n)     { this.config.retries = n; return this; }

  build() {
    // validasi di sini
    if (!this.config.url) throw new Error("URL required");
    return new HttpRequest({ ...this.config });
  }
}

Kunci fluent API: setiap method return this agar bisa di-chain. build() di akhir — validasi + freeze config + bikin object final.

Dunia nyata di ekosistem JS/PHP:

Variasi: immutable builder.

Daripada mutasi this, tiap method return builder baru:

header(k, v) {
  return new HttpRequestBuilder({
    ...this.config,
    headers: { ...this.config.headers, [k]: v },
  });
}

Keuntungan: aman dibagi antar thread/async context, bisa "fork" config di tengah jalan. Kerugian: sedikit overhead alokasi.

Kapan pakai:

Kapan JANGAN pakai:

Trade-off:

Builder menambah kelas tambahan dan sedikit boilerplate, tapi hasilnya call-site yang jauh lebih readable dan validasi terpusat. Di JS, pola {config object} sering jadi alternatif ringan untuk kasus sederhana.

Yang akan kamu pelajari