Builder — základy vzoru stavitel v mobilním vývoji

Autor: IT Sectr Publikováno: 2026-02-17 Doba čtení: 7 min

Builder — vytvářecí vzor, který umožňuje vytvářet složité objekty krok za krokem. Na rozdíl od konstruktoru s desítkou parametrů Builder skládá objekt prostřednictvím řetězce volání, z nichž každé nastavuje jedno pole. Vzor je zvláště užitečný pro objekty s mnoha volitelnými parametry: konfigurace síťového klienta, nastavení databáze, stavitelé alertů a navigace. Více na Refactoring Guru: Builder.

Hlavní body

  • Builder — postupné vytváření objektů s oddělením procesu a výsledku
  • Fluent interface — řetězec volání set()/with() pro pohodlné nastavení
  • Neměnnost — Builder vytváří hotový objekt, který nevyžaduje settery
  • Zpětná kompatibilita — nová pole se přidávají do Builderu bez narušení klientů
  • Kotlin DSL vs Builder — Kotlin nabízí type-safe builders jako alternativu

Co je Builder: podstata vzoru stavitel?

Builder (stavitel) — vytvářecí vzor GoF, který odděluje vytváření složitého objektu od jeho reprezentace. Stejný proces vytváření může vytvářet různé reprezentace. Builder je užitečný, když má objekt mnoho volitelných parametrů a konstruktor s deseti poli je nečitelný a nepružný. Vzor také řeší problém Telescoping Constructor — anti-vzoru, kde počet přetížení konstruktoru roste exponenciálně.

Struktura Builder zahrnuje vnitřní statickou třídu Builder s poli, která kopírují pole hlavní třídy. Každá set-metoda vrací Builder (this) pro fluent chaining. Finální build() metoda vytváří cílový objekt předáním hodnot polí soukromému konstruktoru. Hlavní třída má soukromý konstruktor přijímající Builder. Klient: Object.builder().setField1(val1).setField2(val2).build().

Kdy použít Builder — objekty s 5+ poli, z nichž pouze 2-3 jsou povinná. Konfigurační objekty (RequestConfig, DatabaseConfig). Objekty se složitou logikou validace při vytváření. Objekty, které by měly být po vytvoření neměnné (immutable). V Androidu je Builder aktivně používán v SDK: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.

Builder v Kotlin: klasická a DSL implementace

Kotlin Builder má dva přístupy: klasický Java-style Builder (prostřednictvím vnořené třídy) a Kotlin-style DSL builder (prostřednictvím lambdy s přijímačem). Java-style Builder je preferován pro kompatibilitu s Androidem a při použití s Java kódem. DSL builder — idiomatický způsob Kotlin: funkce přijímá lambdu, uvnitř které je this kontext Builder, kde lze pole přímo přiřazovat.

kotlin
// Klasický 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)
        }
    }
}

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

Kotlin DSL builder — alternativa bez vnořené třídy. Builder-funkce přijímá lambdu v kontextu objektu-stavitele. To je idiomatické pro Kotlin a nevyžaduje write-pole. DSL builders jsou aktivně používány v Ktor Client, kotlinx.serialization, Compose (Modifier). DSL builder není kompatibilní s Java a není vhodný pro knihovny s Java API.

Builder ve Swift: result builders a řetězce

Swift Builder — Swift nemá vestavěný vzor Builder, ale fluent interface lze snadno implementovat pomocí metod vracejících Self. Každá metoda nastavuje vlastnost a vrací self. Na rozdíl od Kotlin, Swift nevyžaduje samostatnou třídu Builder — lze vrátit samotný objekt, pokud je ve fázi sestavování mutable. Pro immutable objekty se používá vnořená třída Builder analogicky s 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 zavedl @resultBuilder — jazykový mechanismus pro deklarativní vytváření struktur. SwiftUI, AttributedString, SceneBuilder používají result builders. To je alternativa ke klasickému Builderu: místo řetězce set-metod result builder používá blok kódu s prvky, které kompilátor shromažďuje do pole nebo stromu. @ViewBuilder ve SwiftUI — nejznámější příklad: uvnitř body lze psát if, switch, ForEach a kompilátor vytváří View z podmínek.

Builder vs Telescoping Constructor: srovnání přístupů

Telescoping Constructor — anti-vzor, kde třída má několik přetížených konstruktorů s různými sadami parametrů. Například tři konstruktory: HttpConfig(url), HttpConfig(url, timeout), HttpConfig(url, timeout, retries). S růstem parametrů počet konstruktorů roste exponenciálně — pro n volitelných polí je potřeba n! kombinací. Builder řeší tento problém tím, že umožňuje nastavit pouze potřebná pole.

VlastnostTelescoping ConstructorBuilderKotlin named args
Množství kóduExponenciální růstLineární růstMinimální
ČitelnostNízká (který parametr?)Vysoká (metoda + název)Vysoká (název = hodnota)
NeměnnostImmutableImmutableImmutable
Java kompatibilitaPlnáPlnáNe (pouze Kotlin)
ValidaceV každém konstruktoruV build() — jednouV init()

Kotlin named arguments + default values — elegantní alternativa k Builderu v čistých Kotlin projektech. Parametry konstruktoru mají výchozí hodnoty, klient předává pouze potřebné: HttpConfig(baseUrl = url, timeout = 15_000). Nevýhoda — nemožnost validace povinných polí ve fázi kompilace. Builder poskytuje povinná pole prostřednictvím konstruktoru Builder (baseUrl je povinný). Pro Java knihovny zůstává Builder de facto standardem.

Builder v Android SDK: AlertDialog, Retrofit, OkHttp

Builder v Android SDK — jeden z nejrozšířenějších vzorů ve standardní knihovně. 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().

Proč Google používá Builder — zpětná kompatibilita. Přidání nové metody do Builderu nenarušuje existující kód. Pokud by Google použil konstruktor s 20 parametry, každé nové pole by vyžadovalo nové přetížení. Builder umožňuje přidávat set-metody po léta bez breaking changes. Například NotificationCompat.Builder přidal setBubbleMetadata() v Android 11, aniž by ovlivnil existující kód.

Builder v Kotlin knihovnách — Ktor (HttpClientBuilder), Coil (ImageRequest.Builder), Room (Room.databaseBuilder()), Navigation (NavOptionsBuilder). V Kotlin projektech se Builder často kombinuje s DSL: Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build(). Vzor zůstává relevantní pro veřejná API, kde je důležitá zpětná kompatibilita a Java interoperabilita.

Často kladené otázky

Kdy je Builder nadbytečný?

Builder je nadbytečný pro objekty s 1-3 poli — běžný konstruktor nebo data class jsou srozumitelnější. Také je nadbytečný v Kotlin projektech bez Java interoperability, kde named arguments + default values řeší stejný úkol jednodušeji. Builder je opodstatněný pro 5+ polí, složitou validaci nebo Java API, kde named arguments nejsou dostupné.

Čím se Builder liší od Factory?

Builder vytváří jeden složitý objekt krok za krokem (nastavení polí), Factory vytváří objekt celý podle typu nebo parametrů. Builder odpovídá na otázku «jak sestavit?», Factory — «co vytvořit?». Builder se často kombinuje s Factory: Factory vybírá typ, Builder nastavuje pole.

Je Builder potřeba ve SwiftUI?

Ve SwiftUI roli Builderu plní result builders (@ViewBuilder, @SceneBuilder) a modifikátory View (.font(), .padding()). Klasický Builder není potřeba, protože SwiftUI používá deklarativní přístup a fluent modifiers. Pro UIKit komponenty je Builder užitečný: UIAlertController, URLRequest, NSAttributedString.

Jak udělat Builder thread-safe?

Builder obvykle nevyžaduje bezpečnost vláken, protože se používá v jednom vlákně pro sestavení objektu. Pokud je Builder používán ve vícevláknovém prostředí (vzácný případ), synchronizujte každou set-metodu a build(). Alternativa — Immutable Builder: každá set-metoda vrací novou instanci Builderu se změněným polem.

Proč Retrofit používá Builder, ne DI?

Retrofit.Builder je veřejné API knihovny, které musí fungovat bez DI kontejneru. Builder poskytuje flexibilitu konfigurace (baseUrl, konvertory, interceptory, vlastní call adaptéry) bez závislostí na Dagger nebo jiném DI. Uvnitř aplikace může DI vytvořit Retrofit jednou přes Builder, ale samotný Builder zůstává součástí veřejného API Retrofit.

Shrnutí

  • Builder — postupné vytváření objektů s fluent interface
  • Kotlin Builder — klasický (vnořená třída) a DSL (lambda s přijímačem)
  • Swift Builder — vnořená třída nebo @resultBuilder pro deklarativní kód
  • Neměnnost — Builder vytváří immutable objekty přes soukromý konstruktor
  • Android SDK — AlertDialog, Retrofit, OkHttp, NotificationCompat — standard odvětví
  • Zpětná kompatibilita — přidávání polí do Builderu nenarušuje existující kód
  • Alternativa Kotlin — named arguments + default values jednodušší pro čisté Kotlin projekty

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také