Builder — dasar-dasar pola pembangun dalam pengembangan mobile

Penulis: IT Sectr Diterbitkan: 2026-02-17 Waktu membaca: 7 mnt

Builder — pola kreasi yang memungkinkan pembuatan objek kompleks secara bertahap. Berbeda dengan konstruktor dengan sepuluh parameter, Builder merakit objek melalui rantai panggilan, yang masing-masing mengatur satu bidang. Pola ini sangat berguna untuk objek dengan banyak parameter opsional: konfigurasi klien jaringan, pengaturan basis data, pembangun alert dan navigasi. Selengkapnya di Refactoring Guru: Builder.

Hal Utama

  • Builder — konstruksi objek bertahap dengan pemisahan proses dan hasil
  • Fluent interface — rantai panggilan set()/with() untuk konfigurasi yang mudah
  • Ketidakberubahan — Builder membuat objek jadi yang tidak memerlukan setter
  • Kompatibilitas mundur — bidang baru ditambahkan ke Builder tanpa merusak klien
  • Kotlin DSL vs Builder — Kotlin menawarkan type-safe builders sebagai alternatif

Apa itu Builder: esensi pola pembangun?

Builder (pembangun) — pola kreasi GoF yang memisahkan konstruksi objek kompleks dari representasinya. Proses pembangunan yang sama dapat menciptakan representasi yang berbeda. Builder berguna ketika suatu objek memiliki banyak parameter opsional dan konstruktor dengan sepuluh bidang tidak terbaca dan tidak fleksibel. Pola ini juga memecahkan masalah Telescoping Constructor — anti-pola di mana jumlah kelebihan muatan konstruktor tumbuh secara eksponensial.

Struktur Builder mencakup kelas statis internal Builder dengan bidang-bidang yang menyalin bidang kelas utama. Setiap metode set mengembalikan Builder (this) untuk fluent chaining. Metode final build() membuat objek target, meneruskan nilai bidang ke konstruktor privat. Kelas utama memiliki konstruktor privat yang menerima Builder. Klien: Object.builder().setField1(val1).setField2(val2).build().

Kapan menggunakan Builder — objek dengan 5+ bidang, yang hanya 2-3 wajib. Objek konfigurasi (RequestConfig, DatabaseConfig). Objek dengan logika validasi kompleks saat pembuatan. Objek yang harus tidak berubah (immutable) setelah dibuat. Di Android, Builder digunakan secara aktif di SDK: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.

Builder di Kotlin: implementasi klasik dan DSL

Kotlin Builder memiliki dua pendekatan: Builder klasik gaya Java (melalui kelas bersarang) dan DSL builder gaya Kotlin (melalui lambda dengan receiver). Builder gaya Java lebih disukai untuk kompatibilitas Android dan saat digunakan dengan kode Java. DSL builder — cara idiomatis Kotlin: fungsi menerima lambda, di dalamnya this adalah konteks Builder, di mana bidang dapat ditetapkan secara langsung.

kotlin
// Builder klasik
data class HttpConfig private constructor(
    val baseUrl: String,
    val timeout: Long = 30_000,
    val retries: Int = 3,
    val headers: Map<String, String> = emptyMap()
) {
    class Builder {
        private var baseUrl: String = ""
        private var timeout: Long = 30_000
        private var retries: Int = 3
        private var headers: MutableMap<String, String> = mutableMapOf()

        fun baseUrl(url: String) = apply { this.baseUrl = url }
        fun timeout(ms: Long) = apply { this.timeout = ms }
        fun retries(n: Int) = apply { this.retries = n }
        fun header(key: String, value: String) = apply { headers[key] = value }

        fun build(): HttpConfig {
            require(baseUrl.isNotBlank()) { "baseUrl is required" }
            return HttpConfig(baseUrl, timeout, retries, headers)
        }
    }
}

// Penggunaan
val config = HttpConfig.Builder()
    .baseUrl("https://api.example.com")
    .timeout(15_000)
    .header("Authorization", "Bearer token")
    .build()

Kotlin DSL builder — alternatif tanpa kelas bersarang. Fungsi-pembangun menerima lambda dalam konteks objek-pembangun. Ini idiomatis untuk Kotlin dan tidak memerlukan bidang write. DSL builders digunakan secara aktif di Ktor Client, kotlinx.serialization, Compose (Modifier). DSL builder tidak kompatibel dengan Java dan tidak cocok untuk pustaka dengan API Java.

Builder di Swift: result builders dan rantai

Swift Builder — Swift tidak memiliki pola Builder bawaan, tetapi fluent interface mudah diimplementasikan melalui metode yang mengembalikan Self. Setiap metode mengatur properti dan mengembalikan self. Berbeda dengan Kotlin, Swift tidak memerlukan kelas Builder terpisah — objek itu sendiri dapat dikembalikan jika bersifat mutable pada tahap perakitan. Untuk objek immutable, digunakan kelas Builder bersarang yang mirip dengan Kotlin.

swift
struct NetworkRequest {
    let url: String
    let method: HTTPMethod
    let headers: [String: String]
    let body: Data?
    let timeout: TimeInterval

    final class Builder {
        private var url: String = ""
        private var method: HTTPMethod = .get
        private var headers: [String: String] = [:]
        private var body: Data? = nil
        private var timeout: TimeInterval = 30

        func withURL(_: String) -> Self { /* self */ }
        func withMethod(_: HTTPMethod) -> Self { /* self */ }
        func withHeader(key: String, value: String) -> Self { /* self */ }
        func withBody(_: Data) -> Self { /* self */ }
        func withTimeout(_: TimeInterval) -> Self { /* self */ }

        func build() throws -> NetworkRequest {
            guard !url.isEmpty else { throw BuilderError.missingURL }
            return NetworkRequest(
                url: url, method: method, headers: headers,
                body: body, timeout: timeout
            )
        }
    }
}

Result Builders — Swift 5.4 memperkenalkan @resultBuilder — mekanisme bahasa untuk pembangunan struktur secara deklaratif. SwiftUI, AttributedString, SceneBuilder menggunakan result builders. Ini adalah alternatif untuk Builder klasik: alih-alih rantai metode set, result builder menggunakan blok kode dengan elemen yang dikumpulkan kompiler ke dalam array atau pohon. @ViewBuilder di SwiftUI — contoh paling terkenal: di dalam body dapat ditulis if, switch, ForEach, dan kompiler membangun View dari kondisi-kondisi tersebut.

Builder vs Telescoping Constructor: perbandingan pendekatan

Telescoping Constructor — anti-pola di mana suatu kelas memiliki beberapa konstruktor yang kelebihan muatan dengan kumpulan parameter berbeda. Misalnya, tiga konstruktor: HttpConfig(url), HttpConfig(url, timeout), HttpConfig(url, timeout, retries). Dengan bertambahnya parameter, jumlah konstruktor tumbuh secara eksponensial — untuk n bidang opsional diperlukan n! kombinasi. Builder memecahkan masalah ini dengan memungkinkan pengaturan hanya bidang yang diperlukan.

KarakteristikTelescoping ConstructorBuilderKotlin named args
Jumlah kodePertumbuhan eksponensialPertumbuhan linierMinimal
KeterbacaanRendah (parameter yang mana?)Tinggi (metode + nama)Tinggi (nama = nilai)
KetidakberubahanImmutableImmutableImmutable
Kompatibilitas JavaLengkapLengkapTidak (hanya Kotlin)
ValidasiDi setiap konstruktorDi build() — sekaliDi init()

Kotlin named arguments + default values — alternatif elegan untuk Builder di proyek Kotlin murni. Parameter konstruktor memiliki nilai default, klien hanya meneruskan yang diperlukan: HttpConfig(baseUrl = url, timeout = 15_000). Kekurangan — ketidakmungkinan memvalidasi bidang wajib pada tahap kompilasi. Builder memberikan bidang wajib melalui konstruktor Builder (baseUrl wajib). Untuk pustaka Java, Builder tetap menjadi standar de facto.

Builder di Android SDK: AlertDialog, Retrofit, OkHttp

Builder di Android SDK — salah satu pola paling umum di pustaka standar. AlertDialog.Builder: new AlertDialog.Builder(context).setTitle().setMessage().setPositiveButton().create(). Retrofit.Builder: new Retrofit.Builder().baseUrl().addConverterFactory().build(). OkHttpClient.Builder: new OkHttpClient.Builder().connectTimeout().addInterceptor().build(). NotificationCompat.Builder: setContentTitle().setContentText().setSmallIcon().build().

Mengapa Google menggunakan Builder — kompatibilitas mundur. Menambahkan metode baru di Builder tidak merusak kode yang ada. Jika Google menggunakan konstruktor dengan 20 parameter, setiap bidang baru akan memerlukan kelebihan muatan baru. Builder memungkinkan penambahan metode set selama bertahun-tahun tanpa breaking changes. Misalnya, NotificationCompat.Builder menambahkan setBubbleMetadata() di Android 11, tanpa memengaruhi kode yang ada.

Builder di pustaka Kotlin — Ktor (HttpClientBuilder), Coil (ImageRequest.Builder), Room (Room.databaseBuilder()), Navigation (NavOptionsBuilder). Di proyek Kotlin, Builder sering dikombinasikan dengan DSL: Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build(). Pola ini tetap relevan untuk API publik di mana kompatibilitas mundur dan interoperabilitas Java penting.

Pertanyaan yang Sering Diajukan

Kapan Builder berlebihan?

Builder berlebihan untuk objek dengan 1-3 bidang — konstruktor biasa atau data class lebih mudah dipahami. Juga berlebihan di proyek Kotlin tanpa interoperabilitas Java, di mana named arguments + default values menyelesaikan tugas yang sama dengan lebih sederhana. Builder dibenarkan untuk 5+ bidang, validasi kompleks, atau API Java di mana named arguments tidak tersedia.

Apa perbedaan Builder dengan Factory?

Builder membuat satu objek kompleks secara bertahap (pengaturan bidang), Factory membuat objek secara keseluruhan berdasarkan jenis atau parameter. Builder menjawab pertanyaan «bagaimana merakit?», Factory — «apa yang dibuat?». Builder sering digabungkan dengan Factory: Factory memilih jenis, Builder mengatur bidang.

Apakah Builder diperlukan di SwiftUI?

Di SwiftUI, peran Builder dilakukan oleh result builders (@ViewBuilder, @SceneBuilder) dan pengubah View (.font(), .padding()). Builder klasik tidak diperlukan karena SwiftUI menggunakan pendekatan deklaratif dan fluent modifiers. Untuk komponen UIKit, Builder berguna: UIAlertController, URLRequest, NSAttributedString.

Bagaimana cara membuat Builder thread-safe?

Builder biasanya tidak memerlukan keamanan thread, karena digunakan dalam satu thread untuk merakit objek. Jika Builder digunakan di lingkungan multi-thread (kasus jarang), sinkronkan setiap metode set dan build(). Alternatif — Immutable Builder: setiap metode set mengembalikan instance Builder baru dengan bidang yang diubah.

Mengapa Retrofit menggunakan Builder, bukan DI?

Retrofit.Builder adalah API publik pustaka yang harus bekerja tanpa wadah DI. Builder memberikan fleksibilitas konfigurasi (baseUrl, konverter, interceptor, adapter panggilan kustom) tanpa ketergantungan pada Dagger atau DI lainnya. Di dalam aplikasi, DI dapat membuat Retrofit sekali melalui Builder, tetapi Builder sendiri tetap menjadi bagian dari API publik Retrofit.

Kesimpulan

  • Builder — konstruksi objek bertahap dengan fluent interface
  • Kotlin Builder — klasik (kelas bersarang) dan DSL (lambda dengan receiver)
  • Swift Builder — kelas bersarang atau @resultBuilder untuk kode deklaratif
  • Ketidakberubahan — Builder membuat objek immutable melalui konstruktor privat
  • Android SDK — AlertDialog, Retrofit, OkHttp, NotificationCompat — standar industri
  • Kompatibilitas mundur — penambahan bidang di Builder tidak merusak kode yang ada
  • Alternatif Kotlin — named arguments + default values lebih sederhana untuk proyek Kotlin murni

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga