Patrón Factory para procesar pagos con match
Clase 18 de 27 • Curso de Patrones de Diseño y SOLID en Python
Contenido del curso
Principios SOLID
- 2

Principio de responsabilidad única en SOLID
05:59 min - 3

Refactorizando código Python con principios SOLID
11:14 min - 4

Cómo aplicar SRP en un procesador de pagos con Stripe
25:19 min - 5

Open Closed Principle: extensión sin modificación
02:39 min - 6

Cómo usar clases abstractas en Python
14:46 min - 7

Principio de Liskov en S.O.L.I.D.
03:18 min - 8

Principio de sustitución de Liskov en Python
06:38 min - 9

Interface Segregation: cuándo separar contratos
02:33 min - 10

Segregación de interfaces en procesadores de pagos
09:05 min - 11

Principio de inversión de dependencias explicado
04:13 min - 12

Principio de inversión de dependencias: servicio de pagos flexible
05:56 min
Reestructuración del proyecto
Patrones de Diseño
- 14

Qué son los patrones de diseño: definición y categorías
03:54 min - 15

Strategy Pattern con Python y setprocessor
01:55 min - 16

Strategy Pattern para pagos en Python
10:58 min - 17

Factory Pattern: centralizar creación de objetos
03:05 min - 18

Patrón Factory para procesar pagos con match
Viendo ahora - 19

Patrón Decorator en 5 pasos para funcionalidad dinámica
03:06 min - 20

Patrón decorador en servicios de pagos
12:57 min - 21

Builder Pattern: construcción paso a paso
01:28 min - 22

Builder pattern para servicios de pagos
18:55 min - 23

Observer Pattern en sistemas de eventos
01:48 min - 24

Observer en sistemas de pagos con Python
11:11 min - 25

Chain of Responsibility para validar pagos
02:04 min - 26

Chain of Responsibility en servicios de pagos
16:27 min - 27

Arquitectura robusta para procesadores de pago
03:19 min
Aplicar patrón factory en Python permite encapsular la lógica de creación de objetos y tomar decisiones limpias y reutilizables. Aquí se muestra cómo elegir entre Stripe, offline y local según el PaymentData y su PaymentType, usando enum, match, static method y un protocol para el procesador. Además, se integra en un class method con tipado Self y manejo de errores con ValueError.
¿Qué problema resuelve el patrón factory en pagos?
El objetivo es centralizar la decisión de qué procesador instanciar según la información de pago. El PaymentData ahora incluye un tipo mediante un enum de Python con valores: offline u online. El tipo por defecto es online, lo que aporta contexto sobre cómo cobrar.
- Si el tipo es offline, retorna el procesador OfflinePaymentProcessor.
- Si el tipo es online y la moneda es USD, retorna StripePaymentProcessor.
- Si el tipo es online y la moneda no es USD, retorna LocalPaymentProcessor.
- Se define un caso por defecto que lanza
ValueErrorpara tipos no soportados.
Así, la lógica de decisión queda encapsulada y puede reutilizarse en todo el servicio.
¿Cómo implementar PaymentProcessorFactory con match en Python?
La clase PaymentProcessorFactory expone un static method createPaymentProcessor que recibe paymentData y devuelve un PaymentProcessorProtocol. La decisión se implementa con el operador de pattern matching match.
from commons import PaymentData, PaymentType
from processors import (
PaymentProcessorProtocol,
OfflinePaymentProcessor,
StripePaymentProcessor,
LocalPaymentProcessor,
)
class PaymentProcessorFactory:
@staticmethod
def createPaymentProcessor(paymentData: PaymentData) -> PaymentProcessorProtocol:
match paymentData.type:
case PaymentType.OFFLINE:
return OfflinePaymentProcessor()
case PaymentType.ONLINE:
match paymentData.currency:
case "USD":
return StripePaymentProcessor()
case _:
return LocalPaymentProcessor()
case _:
# Caso ejemplo para tipos no soportados
raise ValueError("Tipo de pago no soportado")
Puntos clave:
- PaymentType es un enum con valores offline y online.
- Se usa match con case y _ como caso por defecto.
- El método retorna un PaymentProcessorProtocol, asegurando contrato de integración.
- Se lanza ValueError para señalizar validaciones fallidas.
¿Cómo integrarlo en el servicio con createWithPaymentProcessor?
Se añade un class method que, a partir del paymentData, pide al factory el procesador adecuado y crea la instancia del servicio con los demás atributos que llegan como kwargs: notifier, customer validator, payment validator y logger.
from typing import Self
from factory import PaymentProcessorFactory
class PaymentService:
@classmethod
def createWithPaymentProcessor(cls, paymentData: PaymentData, **kwargs) -> Self:
try:
processor = PaymentProcessorFactory.createPaymentProcessor(paymentData)
return cls(payment_processor=processor, **kwargs)
except ValueError as e:
print("Error creando la clase")
raise e
- Se utiliza Self para indicar que retorna una instancia de la misma clase.
- kwargs actúa como diccionario con los atributos restantes del servicio.
- El
try/exceptcapturaValueErrorlanzada por el factory.
¿Cómo usarlo desde main con PaymentData de ejemplo?
El PaymentData incluye monto, fuente y moneda. Si la moneda es USD y el tipo por defecto es online, se selecciona Stripe.
from commons import PaymentData
paymentData = PaymentData(
amount=100,
source="stock visa",
currency="USD", # type por defecto: online
)
service = PaymentService.createWithPaymentProcessor(
paymentData,
notifier=notifier,
customer_validator=customer_validator,
payment_validator=payment_validator,
logger=logger,
)
¿Qué habilidades y conceptos aplicas aquí?
- Patrón factory: encapsular creación y aislar reglas de negocio.
- Enums:
PaymentTypeconofflineyonline. - Match/case en Python para decisiones claras y anidadas.
- Protocolos:
PaymentProcessorProtocolcomo contrato de integración. - Métodos estáticos y de clase: static method para crear, class method para orquestar.
- Tipado avanzado: uso de Self y tipos explícitos.
- Manejo de errores:
ValueErrorpara entradas no soportadas. - Composición con kwargs: pasar
notifier,customer validator,payment validatoryloggeral constructor. - Depuración: uso de breakpoint para verificar el flujo y la instancia seleccionada.
¿De qué otra forma aplicarías patrón factory en este proyecto? Comparte tus ideas en comentarios.