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 — шаблон за креирање фамилија међусобно повезаних или међузависних објеката без навођења њихових конкретних класа. Клијент ради са интерфејсом апстрактне фабрике који дефинише методе за креирање сваког производа фамилије. Конкретна фабрика имплементира интерфејс и креира објекте одређене варијанте. На пример, фабрика 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 објекте, миграције и pool-ове веза. У 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 тестирање, feature flags). За статичке зависности, Hilt потпуно аутоматизује креирање објеката — програмер пише само интерфејс и анотације.
Често постављана питања
Factory Method креира један тип објекта кроз наслеђивање — подкласа преписује фабричку методу. Abstract Factory креира фамилију објеката кроз композицију — интерфејс фабрике декларише методе за више производа. Factory Method је једноставнији, Abstract Factory је флексибилнији за компоненте зависне од платформе или тематске компоненте.
Factory је оправдана за динамички избор имплементације у рантајму (A/B тестови, feature flags, различити API за различите тарифе). DI (Hilt, Dagger, Koin) је пожељнији за статичке зависности — аутоматизује креирање и убризгавање. Factory и DI се не искључују: DI може користити Factory унутар модула.
Factory се тестира заменом фабрике кроз протокол. У тесту се креира TestFactory која имплементира исти протокол и враћа mock-објекте. За статичке Factory методе тестирање је сложеније — захтева DI контејнер или swizzling. Препоручује се увек користити протокол за Factory ради очувања тестирабилности.
ViewModelProvider.Factory — интерфејс из Jetpack-а који омогућава креирање ViewModel са прилагођеним параметрима. Без фабрике, ViewModel се креира кроз рефлексију и може имати само празан конструктор. Factory прима параметре (репозиторијум, application context) и прослеђује их конструктору ViewModel-а. Hilt генерише Factory аутоматски за @HiltViewModel.
Factory реализује Open-Closed принцип: систем је отворен за проширење (нова имплементација се додаје у фабрику), али затворен за модификацију (клијентски код се не мења). Додавање новог типа производа захтева измену само у фабрици, а не у свим клијентима. Ово је кључна предност Factory у односу на директно креирање објеката.
Завршни преглед
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође