Factory — vytvářecí vzor, který deleguje vytváření objektů na tovární metody. V mobilním vývoji se Factory Method a Abstract Factory používají k vytváření ViewModel, NetworkClient, Repository a dalších závislostí. Factory izoluje logiku vytváření instancí, což zjednodušuje výměnu implementací. Více — na Refactoring Guru: Factory Method.
Hlavní body
Factory — vytvářecí návrhový vzor z katalogu GoF. Hlavní myšlenka: přesunout logiku vytváření objektů z klientského kódu do samostatné metody nebo třídy. Klient pracuje s rozhraním nebo abstraktní třídou a konkrétní implementaci vytváří továrna. Tím se implementuje princip obrácení závislostí (Dependency Inversion): klient není závislý na konkrétních třídách, pouze na abstrakcích.
Dvě varianty Factory: Factory Method a Abstract Factory. Factory Method — jedna metoda ve třídě, kterou podtřídy přepisují pro vytváření objektů. Abstract Factory — rozhraní s rodinou továrních metod pro vytváření skupin vzájemně propojených objektů. Obě varianty řeší stejný problém: klient nevolá přímo new MyClass(), ale žádá továrnu, aby vytvořila objekt podle jeho typu nebo parametrů.
Factory vs new() — přímé vytváření objektů pevně váže kód na konkrétní implementaci. Factory přidává mezivrstvu: změna implementace vyžaduje úpravu pouze v továrně, ne ve všech klientech. V mobilním vývoji se Factory aktivně používá pro vytváření ViewModel (ViewModelProvider.Factory), síťových klientů (Retrofit.create()), adaptérů seznamů a továren serializace. DI kontejnery (Dagger, Koin) automaticky generují továrny.
Factory Method — metoda deklarovaná v protokolu nebo abstraktní třídě, která vrací objekt určitého typu. Podtřídy tuto metodu implementují a vytvářejí konkrétní instance. Ve Swift to může být static method v protokolu nebo metoda v základní třídě. V Kotlin — companion object s tovární metodou nebo open fun v abstraktní třídě. Vzor je široce používán pro vytváření parserů, továren chyb a stavitelů dotazů.
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()
}
}
}
// Použití
let gateway = PaymentFactory.create(type: .stripe)
Kotlin verze Factory Method používá companion object nebo sealed class k omezení typů. Sealed class zaručuje, že větev when pokrývá všechny možné typy — kompilátor kontroluje úplnost. To je typické pro Android projekty, kde továrna vytváří různé implementace Repository nebo DataSource v závislosti na build flavour nebo konfiguraci.
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 — vzor pro vytváření rodin vzájemně propojených nebo vzájemně závislých objektů bez zadání jejich konkrétních tříd. Klient pracuje s rozhraním abstraktní továrny, které definuje metody pro vytváření každého produktu rodiny. Konkrétní továrna implementuje rozhraní a vytváří objekty určité varianty. Například továrna UI komponent pro iOS vytváří UIButton, UILabel, UITableView a pro Android — Button, TextView, RecyclerView.
Abstract Factory vs Factory Method — Factory Method vytváří jeden typ objektu prostřednictvím dědičnosti, Abstract Factory vytváří rodinu objektů prostřednictvím kompozice. Factory Method se přepisuje v podtřídách, Abstract Factory poskytuje několik továrních metod prostřednictvím protokolu. Abstract Factory často obsahuje několik Factory Method. V mobilním vývoji se Abstract Factory používá pro komponenty závislé na platformě, motivy a továrny databází.
| Vlastnost | Factory Method | Abstract Factory |
|---|---|---|
| Počet produktů | Jeden | Rodina (několik) |
| Mechanismus | Dědičnost (override) | Kompozice (protocol/interface) |
| Příklad iOS | PaymentFactory.create() | UIComponentFactory pro iOS/Android |
| Příklad Android | ViewModelProvider.Factory | ThemeFactory: vytváření tlačítek, textů, karet |
| Flexibilita | Jednoduchá výměna podtřídy | Úplná výměna rodiny |
Reálný případ Abstract Factory v Android — implementace různých typů databází (SQLite vs Room) prostřednictvím jednotného rozhraní DatabaseFactory. Továrna vytváří DAO objekty, migrace a fondy připojení. V iOS — továrna služeb pro různá prostředí (Development/Staging/Production). Abstract Factory se zřídka používá přímo — její funkce přebírají DI kontejnery (Dagger Module, Swinject Assembly).
Swift Factory je implementována prostřednictvím protokolů a statických metod. Protokol Factory deklaruje metodu create(), která vrací abstraktní typ. Konkrétní továrna implementuje protokol a vytváří potřebné objekty. Swift nevyžaduje samostatnou tovární třídu pro jednoduché případy — stačí statická metoda v enum nebo struct. Pro složité scénáře se používá protokol Factory s vkládáním prostřednictvím DI.
Factory v iOS SDK — mnoho systémových továren: UIStoryboard.instantiateViewController(withIdentifier:), NSKeyedUnarchiver.unarchivedObject(ofClass:from:), JSONDecoder().decode(_:from:). Vývojáři vytvářejí továrny pro ViewController (StoryboardFactory), pro služby (ServiceFactory) a pro datové modely. Factory Method se aktivně používá v architekturách VIPER a Clean Swift pro vytváření modulů obrazovek.
Factory + DI — moderní alternativa: DI kontejner (Swinject, Factory) automaticky generuje továrny pro registrované typy. Kontejner ukládá recepty na vytváření objektů a řeší závislosti. Knihovna Factory (github.com/hmlongco/Factory) používá @Injected(.service) pro automatické vkládání. DI továrny se testují nahrazením celého modulu jedním řádkem: container.register { MockService() }.
Android Factory — klasický příklad: ViewModelProvider.Factory pro vytváření ViewModel s parametry. Google doporučuje používat Hilt pro automatické generování továren ViewModel — anotace @HiltViewModel automaticky vytváří Factory. Pro jednoduché objekty se používá companion object s metodou create() nebo invoke(). V Kotlin umožňuje operátor invoke volat továrnu jako funkci: Factory(param).
Factory v Jetpack Compose — továrny se používají pro vytváření stavů a efektů. remember { Factory.create() } vytvoří objekt při prvním vykreslení a uchovává jej po dobu životnosti composable. ViewModel v Compose se vytváří prostřednictvím viewModel() — to je továrna spravovaná Hilt. V Compose se továrny vyskytují méně explicitně, protože DI a Compose StateManager přebírají vytváření objektů.
Factory vs Hilt — Dagger/Hilt automaticky generuje továrny ve fázi kompilace. @Module + @Provides nahrazuje Factory Method, @Binds nahrazuje Abstract Factory. Ruční továrny zůstávají relevantní pro dynamický výběr implementace za běhu (A/B testování, feature flags). Pro statické závislosti Hilt zcela automatizuje vytváření objektů — vývojář píše pouze rozhraní a anotace.
Často kladené otázky
Factory Method vytváří jeden typ objektu prostřednictvím dědičnosti — podtřída přepisuje tovární metodu. Abstract Factory vytváří rodinu objektů prostřednictvím kompozice — rozhraní továrny deklaruje metody pro několik produktů. Factory Method je jednodušší, Abstract Factory je flexibilnější pro komponenty závislé na platformě nebo tematické komponenty.
Factory je oprávněná pro dynamický výběr implementace za běhu (A/B testy, feature flags, různá API pro různé tarify). DI (Hilt, Dagger, Koin) je preferováno pro statické závislosti — automatizuje vytváření a vkládání. Factory a DI se vzájemně nevylučují: DI může používat Factory uvnitř modulu.
Factory se testuje nahrazením továrny prostřednictvím protokolu. V testu se vytvoří TestFactory, která implementuje stejný protokol a vrací mock objekty. Pro statické Factory metody je testování obtížnější — vyžaduje DI kontejner nebo swizzling. Doporučuje se vždy používat protokol pro Factory pro zachování testovatelnosti.
ViewModelProvider.Factory — rozhraní z Jetpack, které umožňuje vytvářet ViewModel s vlastními parametry. Bez továrny je ViewModel vytvářen prostřednictvím reflexe a může mít pouze prázdný konstruktor. Factory přijímá parametry (repository, application context) a předává je konstruktoru ViewModel. Hilt generuje Factory automaticky pro @HiltViewModel.
Factory implementuje princip Open-Closed: systém je otevřený pro rozšíření (nová implementace se přidá do továrny), ale uzavřený pro modifikaci (klientský kód se nemění). Přidání nového typu produktu vyžaduje změnu pouze v továrně, ne ve všech klientech. To je klíčová výhoda Factory oproti přímému vytváření objektů.
Shrnutí
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í.
Přečtěte si také