Patrón decorador en servicios de pagos
Clase 20 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
11:06 min - 19

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

Patrón decorador en servicios de pagos
Viendo ahora - 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 el patrón decorador en Python con protocolos tipados aporta flexibilidad y control. Aquí verás cómo envolver un PaymentService con lógica de logging sin tocar el comportamiento original, usando typing.Protocol, composición con wrap y una implementación limpia con @dataclass.
¿Cómo aplicar el patrón decorador al PaymentService paso a paso?
Para extender un servicio de pagos sin modificarlo, se define una interfaz con Protocol, se implementa la clase principal conforme a esa interfaz y luego se crea un decorador que delega en el servicio real, añadiendo logging.
- Crear el protocolo del servicio con typing.Protocol.
- Hacer que la clase PaymentService implemente ese protocolo.
- Definir un protocolo para los decoradores con el atributo wrap.
- Implementar un decorador de logging que imprime inicio y fin, y delega la lógica.
- Instanciar el decorador en main envolviendo el servicio real.
# service_protocol.py
from typing import Protocol
class PaymentServiceProtocol(Protocol):
def process_transaction(self, customer_data, payment_data): ...
def process_refund(self, transaction_id: str): ...
def setup_recurring(self, customer_data, payment_data): ...
¿Qué protocolos y clases intervienen en el diseño?
Se definen dos abstracciones clave. Primero, el protocolo del servicio que actúa como contrato: especifica firmas, no comportamiento. Segundo, el protocolo del decorador que replica esas firmas y agrega el atributo wrap tipado como PaymentServiceProtocol para delegar la ejecución. Esto asegura sustitución transparente y facilita pruebas.
# decorator_protocol.py
from typing import Protocol
from service_protocol import PaymentServiceProtocol
class PaymentServiceDecoratorProtocol(Protocol):
wrap: PaymentServiceProtocol
def process_transaction(self, customer_data, payment_data): ...
def process_refund(self, transaction_id: str): ...
def setup_recurring(self, customer_data, payment_data): ...
- Protocol: interfaz estructural que define métodos esperados.
- wrap: composición para delegar en el servicio real.
- Firmas replicadas: garantizan compatibilidad con el contrato original.
- Importaciones mínimas: solo lo necesario para tipar y delegar.
¿Cómo mejora el logging sin alterar la lógica original?
El decorador PaymentServiceLogging implementa el protocolo del decorador, usa @dataclass para su construcción y añade prints de inicio y fin alrededor de cada método. La clave es llamar a self.wrap con los mismos parámetros y retornar la respuesta original, manteniendo el comportamiento intacto.
# logging_service.py
from dataclasses import dataclass
from decorator_protocol import PaymentServiceDecoratorProtocol
from service_protocol import PaymentServiceProtocol
@dataclass
class PaymentServiceLogging(PaymentServiceDecoratorProtocol):
wrap: PaymentServiceProtocol
def process_transaction(self, customer_data, payment_data):
print("start process transaction")
response = self.wrap.process_transaction(customer_data, payment_data)
print("finish process transaction")
return response
def process_refund(self, transaction_id: str):
print(f"start process refund: transaction_id={transaction_id}")
response = self.wrap.process_refund(transaction_id)
print("finish process refund")
return response
def setup_recurring(self, customer_data, payment_data):
print("start setup recurring")
response = self.wrap.setup_recurring(customer_data, payment_data)
print("finish setup recurring")
return response
¿Cómo se instancia el decorador en main?
# main.py (fragmento)
from payment_service import PaymentService # implementación existente
from logging_service import PaymentServiceLogging
service = PaymentService(...)
service = PaymentServiceLogging(wrap=service)
service.process_transaction(customer_data, payment_data)
service.process_refund("1234") # si el servicio real no implementa refund, fallará.
En la demostración, el intento de refund sirve para ilustrar el flujo decorado, aunque el servicio real no tenga ese procesador. La idea central se mantiene: extender funcionalidad (logging y depuración) sin modificar el código del servicio.
¿Qué habilidades y keywords refuerzas con este patrón?
- Diseño con Protocol como interfaz estructural.
- Abstracción y contrato de métodos.
- Composición con wrap para delegación.
- Extensibilidad sin modificar comportamiento original.
- Logging y debugging de transacciones.
- Uso de @dataclass para instanciación clara.
¿De qué otras formas aplicarías el patrón decorador en tu PaymentService o en otras capas? Comparte tus ideas y casos en los comentarios.