Factory — un pattern creazionale che delega la creazione di oggetti a metodi factory. Nello sviluppo mobile, Factory Method e Abstract Factory vengono utilizzati per creare ViewModel, NetworkClient, Repository e altre dipendenze. Factory isola la logica di istanziazione, semplificando la sostituzione delle implementazioni. Maggiori dettagli — su Refactoring Guru: Factory Method.
Punti chiave
Factory — un pattern di progettazione creazionale dal catalogo GoF. L'idea principale: spostare la logica di creazione degli oggetti dal codice client a un metodo o classe separata. Il client lavora con un'interfaccia o classe astratta, mentre l'implementazione concreta viene creata dalla factory. Questo implementa il principio di Inversione delle Dipendenze: il client non dipende da classi concrete, solo da astrazioni.
Due varietà di Factory: Factory Method e Abstract Factory. Factory Method — un singolo metodo in una classe che le sottoclassi sovrascrivono per creare oggetti. Abstract Factory — un'interfaccia con una famiglia di metodi factory per creare gruppi di oggetti correlati. Entrambe le varianti risolvono lo stesso problema: il client non chiama new MyClass() direttamente, ma chiede alla factory di creare un oggetto in base al suo tipo o parametri.
Factory vs new() — la creazione diretta di oggetti accoppia fortemente il codice a un'implementazione concreta. Factory aggiunge un livello: cambiare l'implementazione richiede la modifica solo della factory, non di tutti i client. Nello sviluppo mobile, Factory viene utilizzato attivamente per creare ViewModel (ViewModelProvider.Factory), client di rete (Retrofit.create()), adattatori di elenco e factory di serializzazione. I contenitori DI (Dagger, Koin) generano automaticamente le factory.
Factory Method — un metodo dichiarato in un protocollo o classe astratta che restituisce un oggetto di un tipo specifico. Le sottoclassi implementano il metodo, creando istanze concrete. In Swift, può essere un metodo statico in un protocollo o un metodo in una classe base. In Kotlin — un companion object con un metodo factory o open fun in una classe astratta. Il pattern è ampiamente utilizzato per creare parser, factory di errori e costruttori di query.
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()
}
}
}
// Utilizzo
let gateway = PaymentFactory.create(type: .stripe)
Versione Kotlin di Factory Method utilizza companion object o sealed class per limitare i tipi. Sealed class garantisce che il ramo when copra tutti i tipi possibili — il compilatore verifica la completezza. Questo è tipico per i progetti Android dove la factory crea diverse implementazioni di Repository o DataSource in base al build flavour o alla configurazione.
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 — un pattern per creare famiglie di oggetti correlati o interdipendenti senza specificare le loro classi concrete. Il client lavora con l'interfaccia della factory astratta, che definisce metodi per creare ogni prodotto della famiglia. Una factory concreta implementa l'interfaccia e crea oggetti di una variante specifica. Ad esempio, una factory di componenti UI per iOS crea UIButton, UILabel, UITableView, mentre per Android — Button, TextView, RecyclerView.
Abstract Factory vs Factory Method — Factory Method crea un tipo di oggetto tramite ereditarietà, Abstract Factory crea una famiglia di oggetti tramite composizione. Factory Method viene sovrascritto nelle sottoclassi, Abstract Factory fornisce molteplici metodi factory tramite un protocollo. Abstract Factory spesso contiene diversi Factory Method. Nello sviluppo mobile, Abstract Factory viene utilizzato per componenti dipendenti dalla piattaforma, temi di design e factory di database.
| Caratteristica | Factory Method | Abstract Factory |
|---|---|---|
| Numero di prodotti | Uno | Famiglia (multipli) |
| Meccanismo | Ereditarietà (override) | Composizione (protocollo/interfaccia) |
| Esempio iOS | PaymentFactory.create() | UIComponentFactory per iOS/Android |
| Esempio Android | ViewModelProvider.Factory | ThemeFactory: creazione di pulsanti, testi, carte |
| Flessibilità | Semplice sostituzione di sottoclasse | Sostituzione completa della famiglia |
Caso reale di Abstract Factory in Android — implementazione di diversi tipi di database (SQLite vs Room) tramite una singola interfaccia DatabaseFactory. La factory crea oggetti DAO, migrazioni e pool di connessioni. In iOS — una factory di servizi per diversi ambienti (Development/Staging/Production). Abstract Factory viene usato raramente direttamente — le sue funzioni sono assunte dai contenitori DI (Dagger Module, Swinject Assembly).
Swift Factory è implementato tramite protocolli e metodi statici. Il protocollo Factory dichiara un metodo create() che restituisce un tipo astratto. Una factory concreta implementa il protocollo e crea gli oggetti necessari. Swift non richiede una classe factory separata per casi semplici — un metodo statico in un enum o struct è sufficiente. Per scenari complessi, viene utilizzato un protocollo Factory con iniezione DI.
Factory in iOS SDK — molte factory di sistema: UIStoryboard.instantiateViewController(withIdentifier:), NSKeyedUnarchiver.unarchivedObject(ofClass:from:), JSONDecoder().decode(_:from:). Gli sviluppatori creano factory per ViewController (StoryboardFactory), per servizi (ServiceFactory) e per modelli di dati. Factory Method viene utilizzato attivamente nelle architetture VIPER e Clean Swift per creare moduli di schermata.
Factory + DI — un'alternativa moderna: un contenitore DI (Swinject, Factory) genera automaticamente factory per i tipi registrati. Il contenitore memorizza ricette di creazione oggetti e risolve le dipendenze. La libreria Factory (github.com/hmlongco/Factory) utilizza @Injected(.service) per l'iniezione automatica. Le factory DI vengono testate sostituendo un intero modulo con una singola riga: container.register { MockService() }.
Android Factory — un esempio classico: ViewModelProvider.Factory per creare ViewModel con parametri. Google raccomanda l'uso di Hilt per la generazione automatica di factory ViewModel — l'annotazione @HiltViewModel crea Factory automaticamente. Per oggetti semplici, viene utilizzato un companion object con metodo create() o invoke(). In Kotlin, l'operatore invoke permette di chiamare la factory come una funzione: Factory(param).
Factory in Jetpack Compose — le factory vengono utilizzate per creare stati ed effetti. remember { Factory.create() } crea un oggetto al primo rendering e lo preserva per la durata del composable. ViewModel in Compose viene creato tramite viewModel() — questa è una factory gestita da Hilt. In Compose, le factory sono meno comuni esplicitamente, poiché DI e Compose StateManager gestiscono la creazione degli oggetti.
Factory vs Hilt — Dagger/Hilt genera automaticamente factory in fase di compilazione. @Module + @Services sostituisce Factory Method, @Binds sostituisce Abstract Factory. Le factory manuali rimangono rilevanti per la selezione dinamica dell'implementazione in fase di esecuzione (test A/B, feature flag). Per le dipendenze statiche, Hilt automatizza completamente la creazione di oggetti — lo sviluppatore scrive solo interfacce e annotazioni.
Domande frequenti
Factory Method crea un tipo di oggetto tramite ereditarietà — la sottoclasse sovrascrive il metodo factory. Abstract Factory crea una famiglia di oggetti tramite composizione — l'interfaccia factory dichiara metodi per molteplici prodotti. Factory Method è più semplice, Abstract Factory è più flessibile per componenti dipendenti dalla piattaforma o tematici.
Factory è giustificata per la selezione dinamica dell'implementazione in fase di esecuzione (test A/B, feature flag, API diversa per diversi livelli). DI (Hilt, Dagger, Koin) è preferibile per dipendenze statiche — automatizza creazione e iniezione. Factory e DI non si escludono a vicenda: DI può utilizzare Factory all'interno di un modulo.
Factory viene testata sostituendo la factory tramite un protocollo. Nel test, viene creata una TestFactory che implementa lo stesso protocollo e restituisce oggetti mock. Per i metodi Factory statici, il test è più complesso — richiede un contenitore DI o swizzling. Si raccomanda di utilizzare sempre un protocollo per Factory per mantenere la testabilità.
ViewModelProvider.Factory è un'interfaccia di Jetpack che permette di creare ViewModel con parametri personalizzati. Senza una factory, ViewModel viene creato tramite riflessione e può avere solo un costruttore vuoto. Factory accetta parametri (repository, contesto dell'applicazione) e li passa al costruttore di ViewModel. Hilt genera Factory automaticamente per @HiltViewModel.
Factory implementa il Principio Aperto/Chiuso: il sistema è aperto all'estensione (una nuova implementazione viene aggiunta alla factory) ma chiuso alla modifica (il codice client non cambia). Aggiungere un nuovo tipo di prodotto richiede la modifica solo della factory, non di tutti i client. Questo è il vantaggio chiave di Factory rispetto alla creazione diretta di oggetti.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche