Builder — mga batayan ng pattern ng tagabuo sa mobile development

May-akda: IT Sectr Nai-publish: 2026-02-17 Oras ng pagbabasa: 7 min

Builder — isang creational pattern na nagpapahintulot sa paggawa ng mga kumplikadong object nang step-by-step. Hindi tulad ng constructor na may sampung parameter, ang Builder ay nag-assemble ng object sa pamamagitan ng chain ng mga tawag, bawat isa ay nagse-set ng isang field. Ang pattern ay lalong kapaki-pakinabang para sa mga object na may maraming opsyonal na parameter: configuration ng network client, mga setting ng database, mga tagabuo ng alert at navigation. Higit pa sa Refactoring Guru: Builder.

Mga Pangunahing Punto

  • Builder — step-by-step na pagbuo ng object na may paghihiwalay ng proseso at resulta
  • Fluent interface — chain ng set()/with() na tawag para sa madaling configuration
  • Hindi pagbabago — gumagawa ang Builder ng handa na object na hindi nangangailangan ng setter
  • Backward compatibility — mga bagong field ay idinaragdag sa Builder nang hindi sinisira ang mga kliyente
  • Kotlin DSL vs Builder — nag-aalok ang Kotlin ng type-safe builders bilang alternatibo

Ano ang Builder: esensya ng pattern ng tagabuo?

Builder (tagabuo) — isang GoF creational pattern na naghihiwalay sa pagbuo ng isang kumplikadong object mula sa representasyon nito. Ang parehong proseso ng pagbuo ay maaaring lumikha ng iba't ibang representasyon. Ang Builder ay kapaki-pakinabang kapag ang isang object ay maraming opsyonal na parameter at ang constructor na may sampung field ay hindi nababasa at hindi flexible. Nilulutas din ng pattern ang problema ng Telescoping Constructor — isang anti-pattern kung saan ang bilang ng mga overload ng constructor ay lumalaki nang exponentially.

Structure ng Builder ay may kasamang inner static na Builder class na may mga field na kumukopya ng mga field ng pangunahing klase. Ang bawat set-method ay nagbabalik ng Builder (this) para sa fluent chaining. Ang final na build() method ay gumagawa ng target na object, na ipinapasa ang mga halaga ng field sa pribadong constructor. Ang pangunahing klase ay may pribadong constructor na tumatanggap ng Builder. Kliyente: Object.builder().setField1(val1).setField2(val2).build().

Kailan gagamitin ang Builder — mga object na may 5+ field, kung saan 2-3 lang ang mandatory. Mga configuration object (RequestConfig, DatabaseConfig). Mga object na may kumplikadong validation logic sa paggawa. Mga object na dapat hindi mababago (immutable) pagkatapos gawin. Sa Android, aktibong ginagamit ang Builder sa SDK: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.

Builder sa Kotlin: klasiko at DSL na implementasyon

Kotlin Builder ay may dalawang approach: klasikong Java-style Builder (sa pamamagitan ng nested class) at Kotlin-style DSL builder (sa pamamagitan ng lambda na may receiver). Ang Java-style Builder ay mas gusto para sa Android compatibility at kapag ginagamit sa Java code. DSL builder — idiomatic na paraan ng Kotlin: ang function ay tumatanggap ng lambda, sa loob nito ang this ay ang Builder context, kung saan ang mga field ay maaaring direktang italaga.

kotlin
// Klasikong Builder
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)
        }
    }
}

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

Kotlin DSL builder — alternatibo nang walang nested class. Ang builder-function ay tumatanggap ng lambda sa konteksto ng object-tagabuo. Ito ay idiomatic para sa Kotlin at hindi nangangailangan ng write-field. Ang DSL builders ay aktibong ginagamit sa Ktor Client, kotlinx.serialization, Compose (Modifier). Ang DSL builder ay hindi compatible sa Java at hindi angkop para sa mga library na may Java API.

Builder sa Swift: result builders at mga chain

Swift Builder — walang built-in na Builder pattern ang Swift, ngunit ang fluent interface ay madaling ma-implement sa pamamagitan ng mga method na nagbabalik ng Self. Bawat method ay nagse-set ng property at nagbabalik ng self. Hindi tulad ng Kotlin, hindi nangangailangan ang Swift ng hiwalay na Builder class — ang object mismo ay maaaring ibalik kung ito ay mutable sa yugto ng assembly. Para sa mga immutable object, ginagamit ang nested Builder class katulad ng 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 — ipinakilala ng Swift 5.4 ang @resultBuilder — isang mekanismo ng wika para sa deklaratibong pagbuo ng mga structure. Ang SwiftUI, AttributedString, SceneBuilder ay gumagamit ng result builders. Ito ay alternatibo sa klasikong Builder: sa halip na chain ng set-method, ang result builder ay gumagamit ng code block na may mga element na kinokolekta ng compiler sa isang array o tree. Ang @ViewBuilder sa SwiftUI — pinakakilalang halimbawa: sa loob ng body ay maaaring magsulat ng if, switch, ForEach, at ang compiler ay bumubuo ng View mula sa mga kondisyon.

Builder vs Telescoping Constructor: paghahambing ng mga approach

Telescoping Constructor — isang anti-pattern kung saan ang isang klase ay maraming overloaded na constructor na may iba't ibang set ng parameter. Halimbawa, tatlong constructor: HttpConfig(url), HttpConfig(url, timeout), HttpConfig(url, timeout, retries). Sa pagtaas ng mga parameter, ang bilang ng mga constructor ay lumalaki nang exponentially — para sa n opsyonal na field ay kailangan ng n! kombinasyon. Nilulutas ng Builder ang problemang ito sa pamamagitan ng pagpapahintulot sa pag-set lamang ng mga kinakailangang field.

KatangianTelescoping ConstructorBuilderKotlin named args
Dami ng codeEksponensyal na paglakiLinear na paglakiMinimal
PagkabasaMababa (aling parameter?)Mataas (method + pangalan)Mataas (pangalan = halaga)
Hindi pagbabagoImmutableImmutableImmutable
Java compatibilityBuoBuoHindi (Kotlin lang)
ValidationSa bawat constructorSa build() — isang besesSa init()

Kotlin named arguments + default values — isang eleganteng alternatibo sa Builder sa mga purong Kotlin na proyekto. Ang mga parameter ng constructor ay may mga default na halaga, ang kliyente ay nagpapasa lamang ng mga kailangan: HttpConfig(baseUrl = url, timeout = 15_000). Kahinaan — hindi ma-validate ang mga mandatory field sa yugto ng compilation. Ang Builder ay nagbibigay ng mandatory field sa pamamagitan ng Builder constructor (baseUrl ay mandatory). Para sa mga Java library, ang Builder ay nananatiling de facto standard.

Builder sa Android SDK: AlertDialog, Retrofit, OkHttp

Builder sa Android SDK — isa sa mga pinakakaraniwang pattern sa standard library. 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().

Bakit ginagamit ng Google ang Builder — backward compatibility. Ang pagdaragdag ng bagong method sa Builder ay hindi sumisira sa umiiral na code. Kung gumamit ang Google ng constructor na may 20 parameter, ang bawat bagong field ay mangangailangan ng bagong overload. Ang Builder ay nagpapahintulot ng pagdaragdag ng set-method sa loob ng maraming taon nang walang breaking changes. Halimbawa, ang NotificationCompat.Builder ay nagdagdag ng setBubbleMetadata() sa Android 11, nang hindi naaapektuhan ang umiiral na code.

Builder sa mga Kotlin library — Ktor (HttpClientBuilder), Coil (ImageRequest.Builder), Room (Room.databaseBuilder()), Navigation (NavOptionsBuilder). Sa mga proyektong Kotlin, ang Builder ay madalas na pinagsama sa DSL: Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build(). Ang pattern ay nananatiling may kaugnayan para sa mga pampublikong API kung saan mahalaga ang backward compatibility at Java interoperability.

Mga Madalas Itanong

Kailan kalabisan ang Builder?

Ang Builder ay kalabisan para sa mga object na may 1-3 field — ang ordinaryong constructor o data class ay mas mauunawaan. Kalabisan din sa mga proyektong Kotlin na walang Java interoperability, kung saan ang named arguments + default values ay mas simpleng nilulutas ang parehong gawain. Ang Builder ay makatwiran para sa 5+ field, kumplikadong validation, o Java API kung saan ang named arguments ay hindi available.

Paano naiiba ang Builder sa Factory?

Ang Builder ay gumagawa ng isang kumplikadong object nang step-by-step (pagse-set ng field), ang Factory ay gumagawa ng object nang buo ayon sa uri o parameter. Ang Builder ay sumasagot sa tanong na «paano mag-assemble?», ang Factory — «ano ang gagawin?». Ang Builder ay madalas na pinagsama sa Factory: Pinipili ng Factory ang uri, ang Builder ay nagse-set ng mga field.

Kailangan ba ang Builder sa SwiftUI?

Sa SwiftUI, ang papel ng Builder ay ginagampanan ng result builders (@ViewBuilder, @SceneBuilder) at mga modifier ng View (.font(), .padding()). Ang klasikong Builder ay hindi kailangan dahil ang SwiftUI ay gumagamit ng deklaratibong approach at fluent modifiers. Para sa mga UIKit component, ang Builder ay kapaki-pakinabang: UIAlertController, URLRequest, NSAttributedString.

Paano gawing thread-safe ang Builder?

Ang Builder ay karaniwang hindi nangangailangan ng thread safety, dahil ito ay ginagamit sa isang thread para sa pag-assemble ng object. Kung ang Builder ay ginagamit sa isang multi-thread na kapaligiran (bihirang kaso), i-synchronize ang bawat set-method at build(). Alternatibo — Immutable Builder: bawat set-method ay nagbabalik ng bagong instance ng Builder na may binagong field.

Bakit gumagamit ang Retrofit ng Builder, hindi DI?

Ang Retrofit.Builder ay ang pampublikong API ng library na dapat gumana nang walang DI container. Ang Builder ay nagbibigay ng flexibility ng configuration (baseUrl, converters, interceptors, custom call adapters) nang walang dependencies sa Dagger o iba pang DI. Sa loob ng application, ang DI ay maaaring gumawa ng Retrofit nang isang beses sa pamamagitan ng Builder, ngunit ang Builder mismo ay nananatiling bahagi ng pampublikong API ng Retrofit.

Buod

  • Builder — step-by-step na pagbuo ng object na may fluent interface
  • Kotlin Builder — klasiko (nested class) at DSL (lambda na may receiver)
  • Swift Builder — nested class o @resultBuilder para sa deklaratibong code
  • Hindi pagbabago — gumagawa ang Builder ng mga immutable object sa pamamagitan ng pribadong constructor
  • Android SDK — AlertDialog, Retrofit, OkHttp, NotificationCompat — pamantayan ng industriya
  • Backward compatibility — pagdaragdag ng field sa Builder ay hindi sumisira sa umiiral na code
  • Alternatibo ng Kotlin — named arguments + default values mas simple para sa mga purong Kotlin na proyekto

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din