La gestione di più metodi di pagamento è uno degli aspetti più impegnativi della costruzione di un'applicazione mobile. Ogni metodo di pagamento, sia che si tratti di carte di credito, PayPal, Apple Pay, Google Pay, o di portafogli specifici per regione come Alipay e WeChat Pay, viene fornito con le proprie API, regole di validazione, gestione degli errori e requisiti di conformità.

Il modello di fabbrica offre una soluzione strutturata a questa complessità. Con l'aggiunta di oggetti metodo di pagamento, si decouples il codice client dalle implementazioni concrete dei pagamenti. Questo rende la vostra applicazione più mantenibile, testable, e pronto a scalare come nuove opzioni di pagamento appaiono inevitabilmente.

In questo articolo, esploreremo come applicare il modello di fabbrica per gestire diversi metodi di pagamento nelle applicazioni mobili, con esempi pratici e best practice. Discuteremo anche come questo modello si allinea con architetture moderne come MVVM e Clean Architecture, e come si può integrare con servizi backend come Directus per memorizzare e recuperare le configurazioni di pagamento dinamicamente.

Capire il modello di fabbrica

Il modello di fabbrica è un modello di design creatore che fornisce un'interfaccia per creare oggetti in una superclasse, ma permette alle sottoclassi di modificare il tipo di oggetti che saranno creati. In termini più semplici, incapsula la logica di istantanee in modo che i clienti non debbano conoscere le classi di cemento; interagiscono solo con un'interfaccia comune.

Questo modello è particolarmente prezioso nelle applicazioni mobili dove il set di metodi di pagamento può crescere nel tempo. Senza una fabbrica, si potrebbe finire con grandi [[] o [] dichiarazioni sparse attraverso la vostra base di codice, ognuno sapendo come costruire un metodo di pagamento specifico.

Quando viene introdotto un nuovo metodo di pagamento, si aggiunge semplicemente una nuova classe di cemento e si aggiorna il metodo di fabbrica. Il resto della vostra applicazione rimane invariato.

Come funziona il modello di fabbrica

Il modello prevede tipicamente tre partecipanti:

  • Product[] – Un'interfaccia o una classe astratta che definisce le operazioni tutti i metodi di pagamento devono supportare (ad esempio , ]).
  • Prodotti concreti[[] – Classi che implementano l'interfaccia del prodotto per ogni metodo di pagamento specifico (ad esempio , ]).
  • Creator (Factory)[] – Una classe (o funzione) che contiene un metodo per creare prodotti. Il metodo accetta un parametro (ad esempio, una stringa o un enum) e restituisce il prodotto concreto appropriato.

Nelle applicazioni mobili, questa fabbrica è spesso un singolo o un servizio iniettato di dipendenza, rendendo più facile scambiare le implementazioni durante i test o quando supporta diverse configurazioni di app.

Perché i metodi di pagamento sono complessi nelle applicazioni mobili

Prima di immergersi nell'implementazione, è utile capire i punti specifici del dolore che si rivolge al modello di fabbrica. La gestione dei pagamenti nelle applicazioni mobili va oltre semplicemente chiamando un API.

  • Multiple SDKs and APIs[ – Ogni fornitore di pagamento offre una propria SDK o REST API.
  • Differenze regionali e regolamentari[[] – Un metodo di pagamento disponibile in un paese potrebbe non essere consentito in un altro. Potrebbe essere necessario scegliere dinamicamente la configurazione di fabbrica in base alla localizzazione dell'utente.
  • Le regole di valutazione[[] – Le carte di credito richiedono il controllo Luhn e la convalida della data di scadenza; i portafogli digitali devono gestire i token; i metodi locali possono applicare specifiche esigenze di campo.
  • Maneggiamento e fallback degli errori[[] – Quando un pagamento non riesce, l'applicazione potrebbe avere bisogno di offrire un metodo alternativo o di riprovare con diversi parametri.
  • Testing[] – Non si desidera colpire server di pagamento reali durante i test delle unità. Il modello di fabbrica consente di iniettare facilmente oggetti di pagamento mock.
  • Configurazione dinamica[[[] – Molte applicazioni prescrivono i metodi di pagamento disponibili da un server remoto (ad esempio, da Directus).

Data queste sfide, un'astrazione di pagamento ben progettata diventa critica. Il modello di fabbrica fornisce quel livello di astrazione.

Implementare il modello di fabbrica per i metodi di pagamento

Mentre gli esempi di codice sono di lingua-agnostica (pseudocode), useremo concetti che si traducono direttamente a Swift, Kotlin, Flutter, o React Native.

Passo 1: Definire l'interfaccia del metodo di pagamento

Iniziare definendo un'interfaccia comune che tutti i metodi di pagamento devono implementare. Questa interfaccia dovrebbe includere metodi universali tra i tipi di pagamento, come e .

interface PaymentMethod {
 func processPayment(amount: Double, currency: String) -> PaymentResult
 func validate() -> Bool
}

Puoi anche includere proprietà come , , o [, che l'interfaccia utente può utilizzare per mostrare opzioni di pagamento.

Fase 2: Creare lezioni di pagamento concrete

Per ogni metodo di pagamento supporti, crei una classe che implementa l'interfaccia []. Queste classi incapsulano tutta la logica specifica del provider.

class CreditCardPayment : PaymentMethod {
 private let cardNumber: String
 private let expiry: String
 private let cvv: String

 init(cardNumber: String, expiry: String, cvv: String) {
 self.cardNumber = cardNumber
 self.expiry = expiry
 self.cvv = cvv
 }

 func validate() -> Bool {
 // Luhn check, expiry date > today, etc.
 return true // simplified
 }

 func processPayment(amount: Double, currency: String) -> PaymentResult {
 // Call Stripe or Braintree SDK
 return PaymentResult.success()
 }
}

class PayPalPayment : PaymentMethod {
 private let token: String

 init(token: String) {
 self.token = token
 }

 func validate() -> Bool {
 return !token.isEmpty
 }

 func processPayment(amount: Double, currency: String) -> PaymentResult {
 // Call PayPal SDK
 return PaymentResult.success()
 }
}

class ApplePayPayment : PaymentMethod {
 private let paymentData: Data

 init(paymentData: Data) {
 self.paymentData = paymentData
 }

 func validate() -> Bool {
 return paymentData.count > 0
 }

 func processPayment(amount: Double, currency: String) -> PaymentResult {
 // Use PassKit or Stripe Apple Pay integration
 return PaymentResult.success()
 }
}

Si noti che ogni classe concreta gestisce la propria convalida e le chiamate SDK. Il resto dell'app non si preoccupa delle differenze, ma solo chiama .

Passo 3: costruire la classe di fabbrica

La classe di fabbrica è responsabile della creazione dell'oggetto metodo di pagamento appropriato in base ai parametri di input. L'ingresso può provenire dalla selezione dell'utente, da un oggetto di configurazione o da una risposta del server (ad esempio, da Directus).

class PaymentFactory {

 static func createPaymentMethod(type: String, parameters: [String: Any]) -> PaymentMethod? {
 switch type {
 case "credit_card":
 guard let cardNumber = parameters["cardNumber"] as? String,
 let expiry = parameters["expiry"] as? String,
 let cvv = parameters["cvv"] as? String else {
 return nil
 }
 return CreditCardPayment(cardNumber: cardNumber, expiry: expiry, cvv: cvv)

 case "paypal":
 guard let token = parameters["token"] as? String else {
 return nil
 }
 return PayPalPayment(token: token)

 case "apple_pay":
 guard let paymentData = parameters["paymentData"] as? Data else {
 return nil
 }
 return ApplePayPayment(paymentData: paymentData)

 default:
 return nil
 }
 }
}

In uno scenario più avanzato, si potrebbe utilizzare un enum invece di una stringa per il tipo, o si potrebbe caricare la configurazione di fabbrica da una sorgente remota. Il punto chiave è che la fabbrica è il solo luogo dove le classi di cemento sono istanziate.

Passo 4: Utilizzo della fabbrica nella tua app

Ora, quando un utente seleziona un metodo di pagamento e fornisce i dettagli necessari, il modello di visualizzazione o il controller deve solo chiamare la fabbrica:

let paymentType = selectedPaymentMethod.type // "credit_card", "paypal", etc.
let parameters = collectInputParameters()
if let paymentMethod = PaymentFactory.createPaymentMethod(type: paymentType, parameters: parameters) {
 paymentMethod.processPayment(amount: total, currency: "USD")
} else {
 // show error – unsupported method or invalid input
}

Questo codice è pulito, testabile e aperto per l'estensione. Aggiungendo un nuovo metodo di pagamento (ad esempio, Google Pay) richiede solo una nuova classe e un caso aggiuntivo nella dichiarazione della fabbrica ], non sono necessari altri cambiamenti.

Variazioni di gestione: Fattorie di Paese-Specifiche e Dinamiche

Nelle app del mondo reale, il set di metodi di pagamento disponibili cambia spesso in base al paese dell'utente, alla versione dell'app o alle regole aziendali.

Suppose you use Directus to store enabled payment methods per region. Your backend returns a JSON object like this:

{
 "methods": ["credit_card", "paypal", "apple_pay"],
 "paypal": { "environment": "sandbox", "clientId": "abc123" }
}

È possibile memorizzare questa configurazione in un repository o nello stato della tua app. Quindi la fabbrica può leggerla in runtime:

class DynamicPaymentFactory {
 private let config: PaymentConfiguration

 init(config: PaymentConfiguration) {
 self.config = config
 }

 func createPaymentMethod(type: String, parameters: [String: Any]) -> PaymentMethod? {
 guard config.methods.contains(type) else { return nil }
 // Use config-specific parameters (e.g., clientId for PayPal)
 // ... switch as before
 }
}

Questo approccio mantiene la tua app adattabile senza richiedere un nuovo rilascio app per ogni cambiamento del fornitore di pagamento.

Vantaggi dell'utilizzo del modello di fabbrica

Ormai, i vantaggi dovrebbero essere chiari. Proviamo a enumerateli più accuratamente.

1. Incapsulamento della creazione di oggetti

Se il costruttore di una classe di pagamento cambia (ad esempio, viene aggiunto un nuovo parametro richiesto), si aggiorna solo la fabbrica e la classe di cemento.

2. osservanza del principio aperto/calogato

Il codice è aperto per l'estensione (condizionando nuovi metodi di pagamento) ma chiuso per la modifica (le classi esistenti non cambiano), riducendo il rischio di introdurre bug nei flussi di pagamento già testati.

3. Test semplificato dell'unità

Poiché la fabbrica può essere mocked o sostituito, è possibile iniettare facilmente oggetti di pagamento falsi durante il test. Ad esempio, è possibile creare un che restituisce sempre un pagamento di successo senza toccare la rete.

4. Organizzazione di codici migliorata

Il modello di fabbrica raggruppa naturalmente le classi correlate (metodo di pagamento) sotto un'interfaccia comune, che rende la base di codice più facile da navigare e capire.

5. Flessibilità Runtime

È possibile combinare la fabbrica con un modello di strategia o modello per modificare il comportamento in base alle condizioni di runtime, ad esempio scegliendo tra un ambiente di prova e di produzione.

6. Scalabilità

Poiché la tua app cresce per supportare decine di metodi di pagamento, il modello di fabbrica si bilancia con grazia. Ogni nuovo metodo è un file separato, e l'interruttore di fabbrica rimane lineare.

Considerazioni reali

Integrazione con iniezione di dipendenza

In moderne architetture mobili (MVM, Clean Architecture, Viper), la fabbrica dovrebbe essere registrata nel vostro contenitore di iniezione di dipendenza. In questo modo, è possibile iniettare una vera fabbrica in produzione e una fabbrica di mock in test. Ad esempio, utilizzando Dagger in Android o Swinject in iOS:

// Swift with Swinject
container.register(PaymentFactoryProtocol.self) { _ in PaymentFactory() }

Gestione degli errori e dei fallimenti

Ritornando o gettando un tipo di errore specifico permette al chiamante di presentare un'interfaccia utente significativa. Allo stesso modo, si potrebbe implementare una fabbrica di fallback che si predefinisce un metodo di pagamento universale se il richiedente non riesce a inizializzare.

Configurazione da Backend (Directus)

Directus può essere utilizzato per memorizzare i metadati del metodo di pagamento, come l'ordine del display, i campi richiesti o anche le regole di convalida personalizzate. La vostra app mobile si adatta a questa configurazione all'avvio e lo passa alla fabbrica.

Ad esempio, si potrebbe creare una collezione in Directus con campi:

  • (string: "credit card", "paypal")
  • [string]
  • (JSON array di nomi di campo)
  • [booleano]

La tua app mobile si avvale di questa raccolta tramite Directus SDK e costruisce dinamicamente il registro della fabbrica, che consente agli stakeholder non sviluppatori di controllare le offerte di pagamento senza modifiche di codice.

Migliori Pratiche Quando si utilizza il modello di fabbrica

  • Tenere sotto controllo la fabbrica semplice.[] Dovrebbe creare solo oggetti. Se vi trovate ad aggiungere logica aziendale (ad esempio, conversione valutaria), estraete ciò in servizi separati.
  • Utilizza la digitazione forte.[] Preferire enums o classi sigillate su stringhe per il tipo di metodo. Questo impedisce errori di runtime da identificatori misspelled e fornisce supporto del compilatore.
  • Document l'interfaccia. Assicurarsi che tutti i membri dell'interfaccia [] hanno contratti chiari. Che cosa fa fare esattamente?
  • Test la fabbrica separatamente.[] Scrivere test di unità che verificano la fabbrica restituisce la classe di cemento corretta per ogni input, e che ritorna nil per i tipi non supportati.
  • Combinare con altri modelli. La fabbrica funziona bene con il modello di strategia (per gestire diversi flussi di pagamento) e il modello di Costruttore (se un metodo di pagamento richiede una configurazione complessa).
  • Considera un registro[] Invece di un interruttore monolitico, è possibile costruire un registro aperto dove le classi di metodo di pagamento si registrano.

Conclusioni

Gestire più metodi di pagamento nelle applicazioni mobili non deve essere una fonte di debito tecnico. Applicando il modello di fabbrica, incapsulate la complessità della creazione di oggetti, rendendo il vostro codebase più pulito, più testable e pronto per l'espansione futura. Il modello rispetta il principio aperto / chiuso, decouples business logica da SDK di terze parti, e si integra perfettamente con architetture moderne e servizi backend come Directus.

Quando si affronta un elenco crescente di opzioni di pagamento, raggiungere per il modello di fabbrica. Ti farà risparmiare tempo, ridurre i bug, e ti permetterà di aggiungere nuovi metodi di pagamento con fiducia.

]Altri dati:]
- Modello di metodo di fabbrica (Wikipedia)
- ]Stripe Payment Quickstart – integrazione mobile[FLT:Direct] - [FLT]