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 استفاده کنیم — اشیاء با ۵+ فیلد که تنها ۲-۳ تای آنها اجباری است. اشیاء پیکربندی (RequestConfig, DatabaseConfig). اشیاء با منطق اعتبارسنجی پیچیده در زمان ایجاد. اشیایی که پس از ایجاد باید تغییرناپذیر (immutable) باشند. در Android از Builder به طور فعال در SDK استفاده می‌شود: AlertDialog.Builder, Retrofit.Builder, OkHttpClient.Builder, NotificationCompat.Builder.

Builder در Kotlin: پیاده‌سازی کلاسیک و DSL

Kotlin Builder دو رویکرد دارد: Builder کلاسیک به سبک Java (از طریق کلاس تو در تو) و DSL builder به سبک Kotlin (از طریق لامبدا با دریافت‌کننده). Builder به سبک Java برای سازگاری با Android و استفاده با کد Java ترجیح داده می‌شود. DSL builder — روش اصطلاحی Kotlin: تابع یک لامبدا دریافت می‌کند که درون آن 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 — جایگزینی بدون کلاس تو در تو. تابع-سازنده یک لامبدا در زمینه شیء سازنده دریافت می‌کند. این برای 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 استاندارد دوفاکتو باقی می‌ماند.

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 از سازنده با ۲۰ پارامتر استفاده می‌کرد، هر فیلد جدید نیاز به یک بارگذاری اضافی جدید داشت. Builder اجازه می‌دهد سال‌ها بدون breaking changes متدهای set اضافه شوند. مثلاً 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 برای اشیاء با ۱-۳ فیلد اضافی است — سازنده معمولی یا data class قابل‌فهم‌تر است. همچنین در پروژه‌های Kotlin بدون قابلیت همکاری با Java اضافی است، جایی که named arguments + default values کار مشابه را ساده‌تر انجام می‌دهند. Builder برای ۵+ فیلد، اعتبارسنجی پیچیده یا 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, مبدل‌ها, interceptors, آداپتورهای تماس سفارشی) را بدون وابستگی به Dagger یا سایر DI فراهم می‌کند. در داخل برنامه، DI می‌تواند یک بار Retrofit را از طریق Builder ایجاد کند، اما خود Builder بخشی از API عمومی Retrofit باقی می‌ماند.

جمع‌بندی

  • Builder — ساخت گام‌به‌گام اشیاء با fluent interface
  • Kotlin Builder — کلاسیک (کلاس تو در تو) و DSL (لامبدا با دریافت‌کننده)
  • Swift Builder — کلاس تو در تو یا @resultBuilder برای کد اعلانی
  • تغییرناپذیری — Builder اشیاء immutable را از طریق سازنده خصوصی ایجاد می‌کند
  • Android SDK — AlertDialog, Retrofit, OkHttp, NotificationCompat — استاندارد صنعت
  • سازگاری با عقب — افزودن فیلدها در Builder کد موجود را نمی‌شکند
  • جایگزین Kotlin — named arguments + default values برای پروژه‌های خالص Kotlin ساده‌تر است

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید