Gerenciar múltiplos métodos de pagamento é um dos aspectos mais desafiadores da construção de um aplicativo móvel. Cada método de pagamento, seja ele cartão de crédito, PayPal, Apple Pay, Google Pay ou carteiras específicas para regiões como Alipay e WeChat Pay, vem com sua própria API, regras de validação, manipulação de erros e requisitos de conformidade. Adicionar um novo método muitas vezes significa tocar várias partes da base de códigos, introduzindo risco e regressão.

O padrão de fábrica oferece uma solução estruturada para esta complexidade. Centralizando a criação de objetos de método de pagamento, ele desvincula o código do cliente das implementações concretas de pagamentos. Isso torna seu aplicativo mais mantenevel, testável e pronto para escalar como novas opções de pagamento inevitavelmente aparecem.

Neste artigo, vamos explorar como aplicar o padrão de fábrica para gerenciar diferentes métodos de pagamento em aplicativos móveis, com exemplos práticos e melhores práticas. Também discutiremos como esse padrão se alinha com arquiteturas modernas como MVM e Arquitetura Limpa, e como você pode integrá-lo com serviços de infraestrutura, como o Directus para armazenar e recuperar configurações de pagamento dinamicamente.

Compreender o padrão de fábrica

O padrão de fábrica é um padrão de design criacional que fornece uma interface para criar objetos em uma superclasse, mas permite que as subclasses alterem o tipo de objetos que serão criados. Em termos mais simples, encapsula a lógica de instanciação para que os clientes não precisem saber as classes de concreto; eles só interagem com uma interface comum.

Este padrão é especialmente valioso em aplicativos móveis onde o conjunto de métodos de pagamento pode crescer ao longo do tempo. Sem uma fábrica, você pode acabar com grandes ou declarações espalhadas em sua base de código, cada um sabendo como construir um método de pagamento específico. Essa abordagem viola o Princípio Aberto/Fechado e torna o código rígido – adicionar um novo método de pagamento requer modificar cada lugar que cria um.

O padrão de fábrica resolve isso colocando toda a lógica de criação em um só lugar. Quando um novo método de pagamento é introduzido, você simplesmente adiciona uma nova classe de concreto e atualiza o método de fábrica. O resto de seu aplicativo permanece inalterado.

Como funciona o padrão de fábrica

O padrão normalmente envolve três participantes:

  • Produto – Uma interface ou classe abstrata que define as operações que todos os métodos de pagamento devem suportar (por exemplo, ], ).
  • Produtos de betão – Classes que aplicam a interface do produto para cada método de pagamento específico (por exemplo, ], ]).
  • Criador (Factory)] – Classe (ou função) que contém um método para criação de produtos. O método aceita um parâmetro (por exemplo, uma cadeia ou um enum) e retorna o produto de concreto apropriado.

Em aplicativos móveis, esta fábrica é muitas vezes um singleton ou um serviço de dependência, tornando fácil trocar implementações durante testes ou quando suporta diferentes configurações de aplicativos.

Por que os métodos de pagamento são complexos em aplicativos móveis

Antes de mergulhar na implementação, é útil entender os pontos de dor específicos que o padrão de fábrica aborda. O manuseio de pagamento em aplicativos móveis vai além de simplesmente chamar uma API. Você tem que considerar:

  • ]Multiplos SDKs e APIs – Cada provedor de pagamento oferece sua própria SDK ou API REST. Integrando-os diretamente na sua lógica de negócios cria um acoplamento apertado.
  • Diferenças regionais e regulatórias – Um método de pagamento disponível em um país pode não ser permitido em outro. Você pode precisar escolher dinamicamente a configuração de fábrica com base no local do usuário.
  • Regras de validação – Os cartões de crédito exigem verificações Luhn e validação da data de validade; carteiras digitais precisam de manipulação de fichas; métodos locais podem aplicar requisitos de campo específicos.
  • Error manuseamento e fallbacks – Quando um pagamento falha, o aplicativo pode precisar oferecer um método alternativo ou tentar novamente com diferentes parâmetros. Uma fábrica centralizada simplifica esta lógica.
  • Teste – Você não quer bater em servidores de pagamento real durante testes unitários. O padrão de fábrica permite que você injete objetos de pagamento simulados facilmente.
  • Configuração dinâmica – Muitos aplicativos obtêm métodos de pagamento disponíveis de um servidor remoto (por exemplo, do Directus). A fábrica pode interpretar essa configuração para criar os objetos certos em tempo de execução.

Dadas estas dificuldades, uma abstração de pagamento bem concebida torna-se crítica. O padrão de fábrica fornece essa camada de abstração.

Implementação do padrão de fábrica para os métodos de pagamento

Vamos caminhar por uma implementação concreta. Enquanto os exemplos de código são o diagnóstico de linguagem (pseudocode), usaremos conceitos que traduzem diretamente para Swift, Kotlin, Flutter ou React Native.

Passo 1: Defina a relação do método de pagamento

Comece definindo uma interface comum que todos os métodos de pagamento devem implementar. Esta interface deve incluir métodos que são universais entre os tipos de pagamento, tais como e .

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

Você também pode incluir propriedades como , , ou , que a UI pode usar para mostrar opções de pagamento.

Passo 2: Criar Classes de Pagamento de Concreto

Para cada método de pagamento que você suporta, crie uma classe que implementa a interface . Essas classes encapsulam toda a lógica específica do provedor.

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()
 }
}

Observe que cada classe de concreto lida com sua própria validação e chamadas SDK. O resto do aplicativo não se importa com as diferenças – ele só chama .

Passo 3: Construir a classe de fábrica

A classe de fábrica é responsável pela criação do objeto do método de pagamento apropriado com base nos parâmetros de entrada. A entrada pode vir da seleção do usuário, de um objeto de configuração ou de uma resposta do servidor (por exemplo, do 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
 }
 }
}

Num cenário mais avançado, você pode usar um enum em vez de um string para o tipo, ou você pode carregar a configuração da fábrica de uma fonte remota. O ponto chave é que a fábrica é o apenas lugar onde as classes de concreto são instanciadas.

Passo 4: Usando a Fábrica em seu aplicativo

Agora, quando um usuário seleciona um método de pagamento e fornece os detalhes necessários, seu modelo de visão ou controlador só precisa chamar a fábrica:

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
}

Este código é limpo, testável e aberto para extensão. Adicionar um novo método de pagamento (por exemplo, Google Pay) requer apenas uma nova classe e um caso adicional na declaração da fábrica —não são necessárias outras alterações.

Manuseamento de Variações: Fábricas específicas e dinâmicas do país

Em aplicativos do mundo real, o conjunto de métodos de pagamento disponíveis muitas vezes muda com base no país do usuário, na versão do aplicativo ou nas regras de negócios. Você pode fazer a fábrica dinâmica alimentando-o com um objeto de configuração.

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" }
}

Você pode armazenar esta configuração em um repositório ou no estado de seu aplicativo. Então, a fábrica pode lê-la em tempo de execução:

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
 }
}

Esta abordagem mantém o aplicativo adaptável sem exigir uma nova versão do aplicativo para cada alteração do provedor de pagamento.

Benefícios de Usar o Padrão de Fábrica

Por agora, as vantagens devem ser claras. Vamos enumerá-las mais detalhadamente.

1. Encapsulamento da Criação de Objetos

A fábrica centraliza a lógica de instanciação. Se o construtor de uma classe de pagamento mudar (por exemplo, é adicionado um novo parâmetro necessário), você só atualiza a fábrica e a classe de concreto. Todos os chamadores permanecem inalterados.

2. Aderência ao princípio aberto/acabado

Seu código está aberto para extensão (adicionando novos métodos de pagamento) mas fechado para modificação (as classes existentes não mudam). Isso reduz o risco de introdução de bugs em fluxos de pagamento já testados.

3. Testes unitários simplificados

Como a fábrica pode ser zombe ou substituída, você pode facilmente injetar objetos de pagamento falsos durante os testes. Por exemplo, você pode criar um que sempre retorna um pagamento bem sucedido sem tocar na rede.

4. Organização de Código Melhorada

O padrão de fábrica naturalmente agrupa classes relacionadas (métodos de pagamento) sob uma interface comum. Isto torna a base de código mais fácil de navegar e compreender.

5. Flexibilidade de execução

Você pode combinar a fábrica com uma estratégia ou padrão de modelo para alterar o comportamento com base em condições de execução, por exemplo, escolher entre um ambiente de teste e produção.

6. Escalabilidade

Como seu aplicativo cresce para suportar dezenas de métodos de pagamento, o padrão de fábrica escala graciosamente. Cada novo método é um arquivo separado, eo interruptor de fábrica permanece linear.

Considerações do Mundo Real

Integração com a injeção de dependência

Em arquiteturas móveis modernas (MVVM, Clean Architecture, Viper), a fábrica deve ser registrada em seu recipiente de injeção de dependência. Desta forma, você pode injetar uma fábrica real em produção e uma fábrica simulada em testes. Por exemplo, usando Dagger no Android ou Swinject no iOS:

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

Tratamento de Erros e Retrocessos

Sua fábrica deve lidar com entrada inválida graciosamente. Retornando ou jogando um tipo de erro específico permite que o chamador apresente uma interface de usuário significativa. Da mesma forma, você pode implementar uma fábrica de retorno que não é um método de pagamento universal se o solicitado não inicializar.

Configuração da infra- estrutura (Directus)

O Directus pode ser usado para armazenar metadados do método de pagamento, como a ordem de apresentação, os campos necessários ou até mesmo as regras de validação personalizadas. O seu aplicativo móvel obtém esta configuração na inicialização e passa- a para a fábrica. Isto desvincula o cliente da lógica de pagamento codificada.

Por exemplo, você pode criar uma coleção em Directus com campos:

  • [[FLT: 24]] (texto: "crédito cartão", "paypal")
  • [[FLT: 25]] (corda)
  • (lista JSON de nomes de campos)
  • ] (booleano)

Seu aplicativo móvel busca esta coleção através do Directus SDK e constrói o registro da fábrica dinamicamente. Este padrão permite que os stakeholders não-developer para controlar ofertas de pagamento sem alterações de código.

Melhores práticas ao usar o padrão de fábrica

  • Mantenha a fábrica simples. Só deve criar objetos. Se você se encontrar adicionando lógica de negócios (por exemplo, conversão de moeda), extraia isso em serviços separados.
  • Use hardping forte. Prefere enums ou classes seladas sobre strings para o tipo de método. Isto evita erros de execução de identificadores digitados incorretamente e lhe dá suporte ao compilador.
  • Documento da interface. Certifique-se de que todos os membros da interface têm contratos claros. O que faz exatamente ? joga ou retorna um erro?
  • Teste a fábrica separadamente.] Escreva testes unitários que verificam a fábrica retorna a classe de concreto correta para cada entrada, e que retorna zero para tipos não suportados.
  • Combinar com outros padrões.] A fábrica funciona bem com o padrão Estratégia (para lidar com diferentes fluxos de pagamento) e o padrão Construtor (se um método de pagamento requer configuração complexa).
  • Considere um registro. Em vez de um interruptor monolítico, você pode construir um registro aberto onde as classes de método de pagamento se registram. Isso é comum nas arquiteturas de plugins.

Conclusão

Gerenciar vários métodos de pagamento em aplicativos móveis não precisa ser uma fonte de dívida técnica. Ao aplicar o padrão de fábrica, você encapsula a complexidade da criação de objetos, tornando sua base de código mais limpa, mais testável e pronta para expansão futura. O padrão respeita o Princípio Aberto/Fechado, separa a lógica de negócios de SDKs de terceiros e se integra sem problemas com arquiteturas modernas e serviços de infraestrutura como o Directus.

Quando você enfrentar uma lista crescente de opções de pagamento, alcance o padrão de fábrica. Ele vai economizar tempo, reduzir erros e deixar você adicionar novos métodos de pagamento com confiança.

Leitura adicional:
- Padrão do Método Fábrica (Wikipedia)[
- Pagamento de escala Início rápido – integração móvel[][
- Recolecções de Directus e Referência API[]