Builder Pattern para Servicio de Pagos en Python
Clase 22 de 27 • Curso de Patrones de Diseño y SOLID en Python
Resumen
¿Cómo implementar el patrón de diseño Builder para servicios de pagos?
El patrón Builder es una potente herramienta de diseño que facilita la construcción de objetos complejos al dividir el proceso en pequeños pasos más manejables y comprensibles. En esta clase, aplicaremos este patrón para estructurar un servicio de pagos, demostrando cómo crear un builder para el servicio de pagos y cómo implementar métodos set para definir sus propiedades. A medida que avanzamos, analizaremos su interacción con otros patrones como Factory, resaltando su flexibilidad y eficacia para lidiar con procesos avanzados de inicialización.
¿Cómo crear una clase Builder en Python?
Para comenzar con el patrón Builder en Python, la creacion de una nueva clase será nuestro primer paso. Esta clase se encargará de la provisión de todos los atributos requeridos para el servicio a implementar.
class PaymentServiceBuilder:
def __init__(self):
self.logger = None
self.paymentValidator = None
self.customerValidator = None
self.paymentProcessor = None
self.notifier = None
Es fundamental hacer que todos los atributos sean opcionales con un valor por defecto de None
. Esto nos permitirá instanciarlos gradualmente con los métodos set.
¿Cómo crear métodos Set para cada atributo?
La creación de métodos set
para inicializar cada atributo es un paso crucial. Estos métodos establecerán los componentes esenciales de manera secuencial:
-
SetLogger: Inicializa un logger sin dependencias adicionales.
def setLogger(self): self.logger = TransactionLogger() return self
-
SetPaymentValidator y SetCustomerValidator: Ambos establecen validadores básicos.
def setPaymentValidator(self): self.paymentValidator = PaymentDataValidator() return self def setCustomerValidator(self): self.customerValidator = CustomerValidator() return self
-
Set del PaymentProcessor: Incorpora una fábrica para selección dinámica del procesador.
def setPaymentProcessor(self, paymentData): self.paymentProcessor = PaymentProcessorFactory.createPaymentProcessor(paymentData) return self
¿Cómo manejar casos con más lógica?
Para atributos que dependen de otras condiciones, como notifier
, utilizamos estructuras de control como if
:
def setNotifier(self, customerData):
if customerData.contactInfo.email:
self.notifier = EmailNotifier()
elif customerData.contactInfo.phoneNumber:
self.notifier = SMSNotifier("MyCustomGateway")
else:
raise ValueError("No se puede seleccionar clase de notificación")
return self
¿Cómo finalizamos el Builder?
Finalmente, creamos un método build
para validar y construir el servicio completo. Validamos que los atributos no sean None
antes de instanciar la clase PaymentService
definitiva:
def build(self):
required_fields = [self.paymentProcessor, self.notifier,
self.customerValidator, self.paymentValidator, self.logger]
if not all(required_fields):
missing = [name for name, value in zip(["paymentProcessor", "notifier",
"customerValidator", "paymentValidator", "logger"], required_fields) if value is None]
raise ValueError(f"Dependencias faltantes: {', '.join(missing)}")
return PaymentService(self.paymentProcessor, self.paymentValidator,
self.customerValidator, self.notifier, self.logger)
Implementación del Builder
Finalmente, veamos cómo el código se ejecuta en un flujo práctico de inicialización del servicio de pagos:
builder = PaymentServiceBuilder()
service = (builder.setLogger()
.setPaymentValidator()
.setCustomerValidator()
.setPaymentProcessor(paymentData)
.setNotifier(customerData)
.build())
Próximos pasos y desafíos
A medida que os volváis más cómodos con el patrón Builder, podéis intentar implementar funciones adicionales, como decoradores que modifiquen el comportamiento de vuestra clase principal. ¡Atrévete a experimentar y mejora contínuamente la modularidad y eficiencia de tu código!