โ† Kembali ke Design Pattern
๐Ÿ”จ
Creational

Builder

Membangun objek kompleks langkah demi langkah lewat fluent interface, memisahkan proses pembuatan dari representasinya.

Masalahnya

Class dengan banyak parameter opsional berujung pada telescoping constructor atau pemanggilan init panjang yang sulit dibaca. Kamu butuh cara rapi untuk membangun objek secara bertahap.

Cara Kerja

  • โ€บMethod chaining (fluent interface) membuat proses pembuatan mudah dibaca
  • โ€บBuilder yang sama bisa menghasilkan representasi yang berbeda
  • โ€บField wajib baru divalidasi saat build() dipanggil
  • โ€บHasilnya immutable: setelah di-build, objeknya sudah lengkap
  • โ€บMenghindari anti-pattern "telescoping constructor"

Kapan Digunakan

โœ“Objek dengan banyak field opsional atau yang bisa dikonfigurasi
โœ“Saat objek perlu dibuat melalui beberapa langkah
โœ“Saat kamu ingin membuat beberapa konfigurasi berbeda dari tipe objek yang sama
โœ“Builder untuk HTTP request, query, atau payload notifikasi

Contoh di Dunia Nyata

๐ŸŽ
iOS

URLComponents, NSAttributedString, UIAlertController + addAction calls

๐Ÿค–
Android

AlertDialog.Builder, Notification.Builder, OkHttpClient.Builder

๐ŸŒ
Web

URLSearchParams, axios config, Knex/TypeORM query builders

Contoh Kode

Swift
struct PushPayload {
    let title: String
    let body: String
    let badge: Int
    let sound: String
    let category: String?
}

final class PushPayloadBuilder {
    private var title = ""
    private var body  = ""
    private var badge = 0
    private var sound = "default"
    private var category: String?

    func title(_ v: String)    -> Self { title    = v; return self }
    func body(_ v: String)     -> Self { body     = v; return self }
    func badge(_ v: Int)       -> Self { badge    = v; return self }
    func sound(_ v: String)    -> Self { sound    = v; return self }
    func category(_ v: String) -> Self { category = v; return self }

    func build() -> PushPayload {
        PushPayload(title: title, body: body, badge: badge,
                    sound: sound, category: category)
    }
}

let payload = PushPayloadBuilder()
    .title("New Message")
    .body("You have 3 unread messages")
    .badge(3)
    .category("MESSAGE")
    .build()