Factory — a creational pattern that delegates object creation to factory methods. In mobile development, Factory Method and Abstract Factory are used to create ViewModel, NetworkClient, Repository and other dependencies. Factory isolates instantiation logic, simplifying implementation replacement. More details — on Refactoring Guru: Factory Method.
Key Takeaways
Factory — a creational design pattern from the GoF catalog. The main idea: move object creation logic out of client code into a separate method or class. The client works with an interface or abstract class, while the concrete implementation is created by the factory. This implements the Dependency Inversion principle: the client does not depend on concrete classes, only on abstractions.
Two varieties of Factory: Factory Method and Abstract Factory. Factory Method — a single method in a class that subclasses override to create objects. Abstract Factory — an interface with a family of factory methods for creating groups of related objects. Both variants solve the same problem: the client does not call new MyClass() directly, but asks the factory to create an object by its type or parameters.
Factory vs new() — direct object creation tightly couples code to a concrete implementation. Factory adds a layer: changing the implementation requires editing only the factory, not all clients. In mobile development, Factory is actively used for creating ViewModel (ViewModelProvider.Factory), network clients (Retrofit.create()), list adapters and serialization factories. DI containers (Dagger, Koin) automatically generate factories.
Factory Method — a method declared in a protocol or abstract class that returns an object of a specific type. Subclasses implement the method, creating concrete instances. In Swift, this can be a static method in a protocol or a method in a base class. In Kotlin — a companion object with a factory method or open fun in an abstract class. The pattern is widely used for creating parsers, error factories, and query builders.
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()
}
}
}
// Usage
let gateway = PaymentFactory.create(type: .stripe)
Kotlin version of Factory Method uses companion object or sealed class to limit types. Sealed class ensures that the when branch covers all possible types — the compiler checks completeness. This is typical for Android projects where the factory creates different Repository or DataSource implementations depending on build flavour or configuration.
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 — a pattern for creating families of related or interdependent objects without specifying their concrete classes. The client works with the abstract factory interface, which defines methods for creating each product of the family. A concrete factory implements the interface and creates objects of a specific variant. For example, a UI component factory for iOS creates UIButton, UILabel, UITableView, while for Android — Button, TextView, RecyclerView.
Abstract Factory vs Factory Method — Factory Method creates one type of object through inheritance, Abstract Factory creates a family of objects through composition. Factory Method is overridden in subclasses, Abstract Factory provides multiple factory methods through a protocol. Abstract Factory often contains several Factory Methods. In mobile development, Abstract Factory is used for platform-dependent components, theme styling, and database factories.
| Characteristic | Factory Method | Abstract Factory |
|---|---|---|
| Number of products | One | Family (multiple) |
| Mechanism | Inheritance (override) | Composition (protocol/interface) |
| iOS example | PaymentFactory.create() | UIComponentFactory for iOS/Android |
| Android example | ViewModelProvider.Factory | ThemeFactory: creating buttons, texts, cards |
| Flexibility | Simple subclass replacement | Complete family replacement |
Real-world case of Abstract Factory in Android — implementing different database types (SQLite vs Room) through a single DatabaseFactory interface. The factory creates DAO objects, migrations, and connection pools. In iOS — a service factory for different environments (Development/Staging/Production). Abstract Factory is rarely used directly — its functions are taken over by DI containers (Dagger Module, Swinject Assembly).
Swift Factory is implemented through protocols and static methods. The Factory protocol declares a create() method returning an abstract type. A concrete factory implements the protocol and creates the required objects. Swift does not require a separate factory class for simple cases — a static method in an enum or struct is sufficient. For complex scenarios, a Factory protocol with DI injection is used.
Factory in iOS SDK — many system factories: UIStoryboard.instantiateViewController(withIdentifier:), NSKeyedUnarchiver.unarchivedObject(ofClass:from:), JSONDecoder().decode(_:from:). Developers create factories for ViewController (StoryboardFactory), for services (ServiceFactory), and for data models. Factory Method is actively used in VIPER and Clean Swift architectures for creating screen modules.
Factory + DI — a modern alternative: a DI container (Swinject, Factory) automatically generates factories for registered types. The container stores object creation recipes and resolves dependencies. The Factory library (github.com/hmlongco/Factory) uses @Injected(.service) for automatic injection. DI factories are tested by replacing an entire module with a single line: container.register { MockService() }.
Android Factory — a classic example: ViewModelProvider.Factory for creating ViewModel with parameters. Google recommends using Hilt for automatic ViewModel factory generation — the @HiltViewModel annotation creates Factory automatically. For simple objects, a companion object with create() or invoke() method is used. In Kotlin, the invoke operator allows calling the factory like a function: Factory(param).
Factory in Jetpack Compose — factories are used for creating states and effects. remember { Factory.create() } creates an object on first render and preserves it throughout the composable's lifecycle. ViewModel in Compose is created via viewModel() — this is a factory managed by Hilt. In Compose, factories are less common explicitly, as DI and Compose StateManager handle object creation.
Factory vs Hilt — Dagger/Hilt automatically generates factories at compile time. @Module + @Providers replaces Factory Method, @Binds replaces Abstract Factory. Manual factories remain relevant for dynamic runtime implementation selection (A/B testing, feature flags). For static dependencies, Hilt fully automates object creation — the developer only writes interfaces and annotations.
Frequently Asked Questions
Factory Method creates one type of object through inheritance — the subclass overrides the factory method. Abstract Factory creates a family of objects through composition — the factory interface declares methods for multiple products. Factory Method is simpler, Abstract Factory is more flexible for platform-dependent or thematic components.
Factory is justified for dynamic runtime implementation selection (A/B tests, feature flags, different API for different tiers). DI (Hilt, Dagger, Koin) is preferable for static dependencies — it automates creation and injection. Factory and DI are not mutually exclusive: DI can use Factory inside a module.
Factory is tested by replacing the factory through a protocol. A TestFactory is created in the test, implementing the same protocol and returning mock objects. For static Factory methods, testing is more complex — it requires a DI container or swizzling. It is recommended to always use a protocol for Factory to maintain testability.
ViewModelProvider.Factory is an interface from Jetpack that allows creating ViewModel with custom parameters. Without a factory, ViewModel is created through reflection and can only have an empty constructor. Factory accepts parameters (repository, application context) and passes them to the ViewModel constructor. Hilt generates Factory automatically for @HiltViewModel.
Factory implements the Open-Closed Principle: the system is open for extension (a new implementation is added to the factory) but closed for modification (client code does not change). Adding a new product type requires editing only the factory, not all clients. This is the key advantage of Factory over direct object creation.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also