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:
- Laravel Query Builder —
DB::table("users")->where("active", 1)->orderBy("name")->limit(10)->get(). Classic Builder. Setiap method menambah ke query config,get()(terminator) kompilasi jadi SQL dan eksekusi. - Knex.js / Kysely — SQL query builder untuk Node.js dengan API mirip Laravel.
- Form builders —
zod.object({...}).refine(...).transform(...). Tiap call return validator baru (immutable builder). - URL builders —
new URL("/api").searchParams.append("q", "...")— bentuk sederhana builder. - Supertest —
request(app).post("/login").set("Auth", "..").send({...}).expect(200).
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:
- Object punya banyak parameter optional (5+)
- Urutan/step pembuatan penting (validate → transform → finalize)
- Kamu ingin API yang readable seperti DSL
- Perlu shared setup dengan variasi kecil di ujung
Kapan JANGAN pakai:
- Object sederhana dengan 2-3 parameter — constructor biasa atau object literal sudah cukup
- Kalau cuma "banyak parameter tapi tidak optional", pakai config object:
new HttpRequest({url, method, ...})— sudah readable tanpa builder overhead
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.