Factory — یک الگوی ایجادکننده است که ایجاد اشیاء را به متدهای کارخانهای واگذار میکند. در توسعه موبایل، Factory Method و Abstract Factory برای ایجاد ViewModel، NetworkClient، Repository و سایر وابستگیها استفاده میشوند. Factory منطق نمونهسازی را ایزوله میکند و جایگزینی پیادهسازیها را ساده میکند. بیشتر — در Refactoring Guru: Factory Method.
نکات اصلی
Factory — الگوی طراحی ایجادکننده از کاتالوگ GoF. ایده اصلی: خارج کردن منطق ایجاد اشیاء از کد مشتری به یک متد یا کلاس جداگانه. مشتری با واسط یا کلاس انتزاعی کار میکند و پیادهسازی مشخص توسط کارخانه ایجاد میشود. این اصل وارونگی وابستگی (Dependency Inversion) را پیادهسازی میکند: مشتری به کلاسهای مشخص وابسته نیست، فقط به انتزاعها وابسته است.
دو گونه Factory: Factory Method و Abstract Factory. Factory Method — یک متد در کلاس که زیرکلاسها برای ایجاد اشیاء آن را بازنویسی میکنند. Abstract Factory — واسطی با خانوادهای از متدهای کارخانهای برای ایجاد گروههایی از اشیاء مرتبط. هر دو گونه یک مسئله را حل میکنند: مشتری مستقیماً new MyClass() را فراخوانی نمیکند، بلکه از کارخانه میخواهد شیء را بر اساس نوع یا پارامترهایش ایجاد کند.
Factory vs new() — ایجاد مستقیم اشیاء کد را به یک پیادهسازی مشخص متصل میکند. Factory یک لایه میانی اضافه میکند: تغییر پیادهسازی فقط در کارخانه نیاز به تغییر دارد، نه در همه مشتریها. در توسعه موبایل، Factory به طور فعال برای ایجاد ViewModel (ViewModelProvider.Factory)، مشتریان شبکه (Retrofit.create())، آداپتورهای لیست و کارخانههای سریالسازی استفاده میشود. کانتینرهای DI (Dagger, Koin) به طور خودکار کارخانهها را تولید میکنند.
Factory Method — متدی که در پروتکل یا کلاس انتزاعی اعلام میشود و یک شیء از نوع مشخص را برمیگرداند. زیرکلاسها این متد را پیادهسازی میکنند و نمونههای مشخصی ایجاد میکنند. در Swift این میتواند static method در پروتکل یا متدی در کلاس پایه باشد. در Kotlin — companion object با متد کارخانهای یا open fun در کلاس انتزاعی. این الگو به طور گسترده برای ایجاد تجزیهگرها، کارخانههای خطا و سازندگان درخواست استفاده میشود.
protocol PaymentGateway {
func processPayment(amount: Decimal) async throws -> PaymentResult
}
final class StripeGateway: PaymentGateway { /* ... */ }
final class ApplePayGateway: PaymentGateway { /* ... */ }
enum PaymentType { case stripe, applePay }
final class PaymentFactory {
// Factory Method
static func create(type: PaymentType) -> PaymentGateway {
switch type {
case .stripe: return StripeGateway()
case .applePay: return ApplePayGateway()
}
}
}
// استفاده
let gateway = PaymentFactory.create(type: .stripe)
نسخه Kotlin Factory Method از companion object یا sealed class برای محدود کردن انواع استفاده میکند. Sealed class تضمین میکند که شاخه when تمام انواع ممکن را پوشش میدهد — کامپایلر کامل بودن را بررسی میکند. این برای پروژههای Android معمول است، جایی که کارخانه پیادهسازیهای مختلف Repository یا DataSource را بسته به build flavour یا پیکربندی ایجاد میکند.
sealed class PaymentType {
object Stripe : PaymentType()
object ApplePay : PaymentType()
}
interface PaymentGateway {
suspend fun processPayment(amount: BigDecimal): PaymentResult
}
class PaymentFactory {
companion object {
fun create(type: PaymentType): PaymentGateway = when (type) {
PaymentType.Stripe -> StripeGateway()
PaymentType.ApplePay -> ApplePayGateway()
}
}
}
Abstract Factory — الگویی برای ایجاد خانوادههایی از اشیاء مرتبط یا وابسته به هم بدون مشخص کردن کلاسهای مشخص آنها. مشتری با واسط کارخانه انتزاعی کار میکند که متدهایی برای ایجاد هر محصول خانواده تعریف میکند. کارخانه مشخص واسط را پیادهسازی میکند و اشیاء یک variant خاص را ایجاد میکند. به عنوان مثال، کارخانه کامپوننتهای UI برای iOS UIButton، UILabel، UITableView ایجاد میکند و برای Android — Button، TextView، RecyclerView.
Abstract Factory vs Factory Method — Factory Method یک نوع شیء را از طریق وراثت ایجاد میکند، Abstract Factory خانوادهای از اشیاء را از طریق ترکیب ایجاد میکند. Factory Method در زیرکلاسها بازنویسی میشود، Abstract Factory چندین متد کارخانهای را از طریق پروتکل ارائه میدهد. Abstract Factory اغلب شامل چندین Factory Method است. در توسعه موبایل، Abstract Factory برای کامپوننتهای وابسته به پلتفرم، تمها و کارخانههای پایگاه داده استفاده میشود.
| ویژگی | Factory Method | Abstract Factory |
|---|---|---|
| تعداد محصولات | یک | خانواده (چندین) |
| مکانیزم | وراثت (override) | ترکیب (protocol/interface) |
| مثال iOS | PaymentFactory.create() | UIComponentFactory برای iOS/Android |
| مثال Android | ViewModelProvider.Factory | ThemeFactory: ایجاد دکمهها، متنها، کارتها |
| انعطافپذیری | جایگزینی ساده زیرکلاس | جایگزینی کامل خانواده |
مورد واقعی Abstract Factory در Android — پیادهسازی انواع مختلف پایگاه داده (SQLite vs Room) از طریق یک واسط یکپارچه DatabaseFactory. کارخانه اشیاء DAO، مهاجرتها و استخرهای اتصال ایجاد میکند. در iOS — کارخانه سرویسها برای محیطهای مختلف (Development/Staging/Production). Abstract Factory به ندرت مستقیماً استفاده میشود — وظایف آن توسط کانتینرهای DI (Dagger Module, Swinject Assembly) انجام میشود.
Swift Factory از طریق پروتکلها و متدهای ایستا پیادهسازی میشود. پروتکل Factory متد create() را اعلام میکند که یک نوع انتزاعی برمیگرداند. کارخانه مشخص پروتکل را پیادهسازی میکند و اشیاء مورد نیاز را ایجاد میکند. Swift برای موارد ساده به یک کلاس-کارخانه جداگانه نیاز ندارد — یک متد ایستا در enum یا struct کافی است. برای سناریوهای پیچیده از پروتکل Factory با تزریق از طریق DI استفاده میشود.
Factory در iOS SDK — بسیاری از کارخانههای سیستمی: UIStoryboard.instantiateViewController(withIdentifier:)، NSKeyedUnarchiver.unarchivedObject(ofClass:from:)، JSONDecoder().decode(_:from:). توسعهدهندگان کارخانههایی برای ViewController (StoryboardFactory)، برای سرویسها (ServiceFactory) و برای مدلهای داده ایجاد میکنند. Factory Method به طور فعال در معماریهای VIPER و Clean Swift برای ایجاد ماژولهای صفحه استفاده میشود.
Factory + DI — جایگزین مدرن: کانتینر DI (Swinject, Factory) به طور خودکار کارخانههایی برای انواع ثبتشده تولید میکند. کانتینر دستورالعملهای ایجاد اشیاء را ذخیره میکند و وابستگیها را حل میکند. کتابخانه Factory (github.com/hmlongco/Factory) از @Injected(.service) برای تزریق خودکار استفاده میکند. کارخانههای DI با جایگزینی کل ماژول با یک خط تست میشوند: container.register { MockService() }.
Android Factory — مثال کلاسیک: ViewModelProvider.Factory برای ایجاد ViewModel با پارامترها. Google استفاده از Hilt را برای تولید خودکار کارخانههای ViewModel توصیه میکند — @HiltViewModel به طور خودکار Factory ایجاد میکند. برای اشیاء ساده از companion object با متد create() یا invoke() استفاده میشود. در Kotlin عملگر invoke به شما امکان میدهد کارخانه را مانند یک تابع فراخوانی کنید: Factory(param).
Factory در Jetpack Compose — کارخانهها برای ایجاد حالتها و اثرات استفاده میشوند. remember { Factory.create() } شیء را در اولین رندر ایجاد میکند و آن را برای طول عمر composable حفظ میکند. ViewModel در Compose از طریق viewModel() ایجاد میشود — این یک کارخانه است که توسط Hilt مدیریت میشود. در Compose کارخانهها کمتر به صورت صریح دیده میشوند، زیرا DI و Compose StateManager ایجاد اشیاء را بر عهده میگیرند.
Factory vs Hilt — Dagger/Hilt به طور خودکار کارخانهها را در مرحله کامپایل تولید میکند. @Module + @Provides جایگزین Factory Method میشود، @Binds جایگزین Abstract Factory میشود. کارخانههای دستی برای انتخاب پویای پیادهسازی در زمان اجرا (تست A/B، پرچمهای ویژگی) همچنان مرتبط هستند. برای وابستگیهای ایستا، Hilt ایجاد اشیاء را کاملاً خودکار میکند — توسعهدهنده فقط واسط و annotationها را مینویسد.
سوالات متداول
Factory Method یک نوع شیء را از طریق وراثت ایجاد میکند — زیرکلاس متد کارخانه را بازنویسی میکند. Abstract Factory خانوادهای از اشیاء را از طریق ترکیب ایجاد میکند — واسط کارخانه متدهایی برای چندین محصول اعلام میکند. Factory Method سادهتر است، Abstract Factory برای کامپوننتهای وابسته به پلتفرم یا موضوعی انعطافپذیرتر است.
Factory برای انتخاب پویای پیادهسازی در زمان اجرا توجیهپذیر است (تستهای A/B، پرچمهای ویژگی، API متفاوت برای تعرفههای مختلف). DI (Hilt, Dagger, Koin) برای وابستگیهای ایستا ترجیح داده میشود — ایجاد و تزریق را خودکار میکند. Factory و DI یکدیگر را رد نمیکنند: DI میتواند از Factory در داخل ماژول استفاده کند.
Factory با جایگزینی کارخانه از طریق پروتکل تست میشود. در تست یک TestFactory ایجاد میشود که همان پروتکل را پیادهسازی میکند و اشیاء ساختگی برمیگرداند. برای متدهای ایستای Factory تست کردن دشوارتر است — به کانتینر DI یا swizzling نیاز دارد. توصیه میشود همیشه از پروتکل برای Factory استفاده کنید تا قابلیت تست حفظ شود.
ViewModelProvider.Factory — واسطی از Jetpack که امکان ایجاد ViewModel با پارامترهای سفارشی را فراهم میکند. بدون کارخانه، ViewModel از طریق بازتاب ایجاد میشود و فقط میتواند سازنده خالی داشته باشد. Factory پارامترها (repository، application context) را دریافت میکند و آنها را به سازنده ViewModel منتقل میکند. Hilt به طور خودکار Factory را برای @HiltViewModel ایجاد میکند.
Factory اصل Open-Closed را پیادهسازی میکند: سیستم برای گسترش باز است (پیادهسازی جدید به کارخانه اضافه میشود)، اما برای تغییر بسته است (کد مشتری تغییر نمیکند). افزودن یک نوع محصول جدید فقط در کارخانه نیاز به تغییر دارد، نه در همه مشتریها. این مزیت کلیدی Factory نسبت به ایجاد مستقیم اشیاء است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.