Builder — βασικές αρχές του προτύπου κατασκευαστή στην ανάπτυξη κινητών

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-17 Χρόνος ανάγνωσης: 7 λεπ

Builder — ένα δημιουργικό πρότυπο που επιτρέπει τη δημιουργία σύνθετων αντικειμένων βήμα προς βήμα. Σε αντίθεση με έναν κατασκευαστή με δέκα παραμέτρους, ο Builder συναρμολογεί το αντικείμενο μέσω μιας αλυσίδας κλήσεων, κάθε μία από τις οποίες ρυθμίζει ένα πεδίο. Το πρότυπο είναι ιδιαίτερα χρήσιμο για αντικείμενα με πολλές προαιρετικές παραμέτρους: διαμόρφωση πελάτη δικτύου, ρυθμίσεις βάσης δεδομένων, κατασκευαστές ειδοποιήσεων και πλοήγησης. Περισσότερα στο Refactoring Guru: Builder.

Κύρια σημεία

  • Builder — σταδιακή κατασκευή αντικειμένων με διαχωρισμό διαδικασίας και αποτελέσματος
  • Fluent interface — αλυσίδα κλήσεων set()/with() για εύκολη ρύθμιση
  • Αμεταβλητότητα — ο Builder δημιουργεί έτοιμο αντικείμενο που δεν απαιτεί setter
  • Συμβατότητα προς τα πίσω — νέα πεδία προστίθενται στον Builder χωρίς να σπάζουν τους πελάτες
  • Kotlin DSL vs Builder — η Kotlin προσφέρει type-safe builders ως εναλλακτική

Τι είναι ο Builder: ουσία του προτύπου κατασκευαστή;

Builder (κατασκευαστής) — ένα δημιουργικό πρότυπο GoF που διαχωρίζει την κατασκευή ενός σύνθετου αντικειμένου από την αναπαράστασή του. Η ίδια διαδικασία κατασκευής μπορεί να δημιουργήσει διαφορετικές αναπαραστάσεις. Ο Builder είναι χρήσιμος όταν ένα αντικείμενο έχει πολλές προαιρετικές παραμέτρους και ένας κατασκευαστής με δέκα πεδία είναι δυσανάγνωστος και μη ευέλικτος. Το πρότυπο λύνει επίσης το πρόβλημα του Telescoping Constructor — ένα αντι-πρότυπο όπου ο αριθμός των υπερφορτώσεων του κατασκευαστή αυξάνεται εκθετικά.

Δομή Builder περιλαμβάνει μια εσωτερική στατική κλάση Builder με πεδία που αντιγράφουν τα πεδία της κύριας κλάσης. Κάθε set-μέθοδος επιστρέφει Builder (this) για fluent chaining. Η τελική build() μέθοδος δημιουργεί το αντικείμενο-στόχο, μεταβιβάζοντας τις τιμές των πεδίων στον ιδιωτικό κατασκευαστή. Η κύρια κλάση έχει έναν ιδιωτικό κατασκευαστή που δέχεται Builder. Πελάτης: Object.builder().setField1(val1).setField2(val2).build().

Πότε να χρησιμοποιείτε τον Builder — αντικείμενα με 5+ πεδία, από τα οποία μόνο 2-3 είναι υποχρεωτικά. Αντικείμενα διαμόρφωσης (RequestConfig, DatabaseConfig). Αντικείμενα με σύνθετη λογική επικύρωσης κατά τη δημιουργία. Αντικείμενα που πρέπει να είναι αμετάβλητα (immutable) μετά τη δημιουργία. Στο Android, ο Builder χρησιμοποιείται ενεργά στο SDK: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.

Builder στην Kotlin: κλασική και DSL υλοποίηση

Kotlin Builder έχει δύο προσεγγίσεις: κλασικό Java-style Builder (μέσω ένθετης κλάσης) και Kotlin-style DSL builder (μέσω lambda με δέκτη). Ο Java-style Builder προτιμάται για συμβατότητα με Android και κατά τη χρήση με κώδικα Java. DSL builder — ιδιωματικός τρόπος Kotlin: η συνάρτηση δέχεται ένα lambda, μέσα στο οποίο το this είναι το περιβάλλον Builder, όπου τα πεδία μπορούν να εκχωρηθούν άμεσα.

kotlin
// Κλασικός 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)
        }
    }
}

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

Kotlin DSL builder — εναλλακτική χωρίς ένθετη κλάση. Η builder-συνάρτηση δέχεται ένα lambda στο περιβάλλον του αντικειμένου-κατασκευαστή. Αυτό είναι ιδιωματικό για την Kotlin και δεν απαιτεί write-πεδία. Οι DSL builders χρησιμοποιούνται ενεργά στο Ktor Client, kotlinx.serialization, Compose (Modifier). Ο DSL builder δεν είναι συμβατός με Java και δεν είναι κατάλληλος για βιβλιοθήκες με Java API.

Builder στην Swift: result builders και αλυσίδες

Swift Builder — η Swift δεν έχει ενσωματωμένο πρότυπο Builder, αλλά το fluent interface υλοποιείται εύκολα μέσω μεθόδων που επιστρέφουν Self. Κάθε μέθοδος ρυθμίζει μια ιδιότητα και επιστρέφει self. Σε αντίθεση με την Kotlin, η Swift δεν απαιτεί ξεχωριστή κλάση Builder — το ίδιο το αντικείμενο μπορεί να επιστραφεί εάν είναι mutable στο στάδιο συναρμολόγησης. Για immutable αντικείμενα, χρησιμοποιείται ένθετη κλάση Builder παρόμοια με την 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 εισήγαγε το @resultBuilder — έναν γλωσσικό μηχανισμό για δηλωτική κατασκευή δομών. Τα SwiftUI, AttributedString, SceneBuilder χρησιμοποιούν result builders. Αυτό είναι μια εναλλακτική του κλασικού Builder: αντί για αλυσίδα set-μεθόδων, ο result builder χρησιμοποιεί ένα μπλοκ κώδικα με στοιχεία που ο μεταγλωττιστής συλλέγει σε πίνακα ή δέντρο. Το @ViewBuilder στο SwiftUI — το πιο γνωστό παράδειγμα: μέσα στο body μπορούν να γραφτούν if, switch, ForEach, και ο μεταγλωττιστής χτίζει View από τις συνθήκες.

Builder vs Telescoping Constructor: σύγκριση προσεγγίσεων

Telescoping Constructor — ένα αντι-πρότυπο όπου μια κλάση έχει πολλαπλούς υπερφορτωμένους κατασκευαστές με διαφορετικά σύνολα παραμέτρων. Για παράδειγμα, τρεις κατασκευαστές: HttpConfig(url), HttpConfig(url, timeout), HttpConfig(url, timeout, retries). Με την αύξηση των παραμέτρων, ο αριθμός των κατασκευαστών αυξάνεται εκθετικά — για n προαιρετικά πεδία χρειάζονται n! συνδυασμοί. Ο Builder λύνει αυτό το πρόβλημα επιτρέποντας τη ρύθμιση μόνο των απαραίτητων πεδίων.

ΧαρακτηριστικόTelescoping ConstructorBuilderKotlin named args
Ποσότητα κώδικαΕκθετική αύξησηΓραμμική αύξησηΕλάχιστη
ΑναγνωσιμότηταΧαμηλή (ποια παράμετρος;)Υψηλή (μέθοδος + όνομα)Υψηλή (όνομα = τιμή)
ΑμεταβλητότηταImmutableImmutableImmutable
Συμβατότητα JavaΠλήρηςΠλήρηςΌχι (μόνο Kotlin)
ΕπικύρωσηΣε κάθε κατασκευαστήΣτο build() — μία φοράΣτο init()

Kotlin named arguments + default values — μια κομψή εναλλακτική του Builder σε καθαρά έργα Kotlin. Οι παράμετροι του κατασκευαστή έχουν προεπιλεγμένες τιμές, ο πελάτης μεταβιβάζει μόνο τις απαραίτητες: HttpConfig(baseUrl = url, timeout = 15_000). Μειονέκτημα — αδυναμία επικύρωσης υποχρεωτικών πεδίων στο στάδιο μεταγλώττισης. Ο Builder παρέχει υποχρεωτικά πεδία μέσω του κατασκευαστή Builder (baseUrl είναι υποχρεωτικό). Για βιβλιοθήκες Java, ο Builder παραμένει το de facto πρότυπο.

Builder στο Android SDK: AlertDialog, Retrofit, OkHttp

Builder στο Android SDK — ένα από τα πιο διαδεδομένα πρότυπα στην τυπική βιβλιοθήκη. 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().

Γιατί η Google χρησιμοποιεί Builder — συμβατότητα προς τα πίσω. Η προσθήκη μιας νέας μεθόδου στον Builder δεν σπάει τον υπάρχοντα κώδικα. Αν η Google χρησιμοποιούσε κατασκευαστή με 20 παραμέτρους, κάθε νέο πεδίο θα απαιτούσε νέα υπερφόρτωση. Ο Builder επιτρέπει την προσθήκη set-μεθόδων για χρόνια χωρίς breaking changes. Για παράδειγμα, το NotificationCompat.Builder πρόσθεσε το setBubbleMetadata() στο Android 11, χωρίς να επηρεάσει τον υπάρχοντα κώδικα.

Builder σε βιβλιοθήκες Kotlin — Ktor (HttpClientBuilder), Coil (ImageRequest.Builder), Room (Room.databaseBuilder()), Navigation (NavOptionsBuilder). Σε έργα Kotlin, ο Builder συχνά συνδυάζεται με DSL: Room.databaseBuilder(context, AppDatabase.class, "db").fallbackToDestructiveMigration().build(). Το πρότυπο παραμένει σχετικό για δημόσια API όπου η συμβατότητα προς τα πίσω και η διαλειτουργικότητα Java είναι σημαντικές.

Συχνές ερωτήσεις

Πότε είναι περιττός ο Builder;

Ο Builder είναι περιττός για αντικείμενα με 1-3 πεδία — ένας συνηθισμένος κατασκευαστής ή data class είναι πιο κατανοητός. Επίσης περιττός σε έργα Kotlin χωρίς διαλειτουργικότητα Java, όπου τα named arguments + default values λύνουν την ίδια εργασία πιο απλά. Ο Builder δικαιολογείται για 5+ πεδία, σύνθετη επικύρωση ή Java API όπου τα named arguments δεν είναι διαθέσιμα.

Πώς διαφέρει ο Builder από το Factory;

Ο Builder δημιουργεί ένα σύνθετο αντικείμενο βήμα προς βήμα (ρύθμιση πεδίων), το Factory δημιουργεί ένα αντικείμενο εξ ολοκλήρου ανά τύπο ή παραμέτρους. Ο Builder απαντά στην ερώτηση «πώς να συναρμολογήσω;», το Factory — «τι να δημιουργήσω;». Ο Builder συχνά συνδυάζεται με το Factory: το Factory επιλέγει τον τύπο, ο Builder ρυθμίζει τα πεδία.

Χρειάζεται Builder στο SwiftUI;

Στο SwiftUI, τον ρόλο του Builder εκτελούν οι result builders (@ViewBuilder, @SceneBuilder) και οι τροποποιητές View (.font(), .padding()). Ο κλασικός Builder δεν απαιτείται, καθώς το SwiftUI χρησιμοποιεί δηλωτική προσέγγιση και fluent modifiers. Για στοιχεία UIKit, ο Builder είναι χρήσιμος: UIAlertController, URLRequest, NSAttributedString.

Πώς να κάνετε τον Builder thread-safe;

Ο Builder συνήθως δεν απαιτεί ασφάλεια νημάτων, καθώς χρησιμοποιείται σε ένα νήμα για τη συναρμολόγηση του αντικειμένου. Εάν ο Builder χρησιμοποιείται σε περιβάλλον πολλαπλών νημάτων (σπάνια περίπτωση), συγχρονίστε κάθε set-μέθοδο και build(). Εναλλακτική — Immutable Builder: κάθε set-μέθοδος επιστρέφει μια νέα παρουσία Builder με το τροποποιημένο πεδίο.

Γιατί το Retrofit χρησιμοποιεί Builder και όχι DI;

Το Retrofit.Builder είναι το δημόσιο API της βιβλιοθήκης που πρέπει να λειτουργεί χωρίς κοντέινερ DI. Ο Builder παρέχει ευελιξία διαμόρφωσης (baseUrl, μετατροπείς, interceptor, προσαρμοσμένους call adapters) χωρίς εξαρτήσεις από Dagger ή άλλα DI. Μέσα στην εφαρμογή, το DI μπορεί να δημιουργήσει το Retrofit μία φορά μέσω Builder, αλλά ο ίδιος ο Builder παραμένει μέρος του δημόσιου API του Retrofit.

Συμπεράσματα

  • Builder — σταδιακή κατασκευή αντικειμένων με fluent interface
  • Kotlin Builder — κλασικός (ένθετη κλάση) και DSL (lambda με δέκτη)
  • Swift Builder — ένθετη κλάση ή @resultBuilder για δηλωτικό κώδικα
  • Αμεταβλητότητα — ο Builder δημιουργεί immutable αντικείμενα μέσω ιδιωτικού κατασκευαστή
  • Android SDK — AlertDialog, Retrofit, OkHttp, NotificationCompat — βιομηχανικό πρότυπο
  • Συμβατότητα προς τα πίσω — η προσθήκη πεδίων στον Builder δεν σπάει τον υπάρχοντα κώδικα
  • Εναλλακτική Kotlin — τα named arguments + default values απλούστερα για καθαρά έργα Kotlin

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης