# FUNDAMENTOS: DESIGN PATTERNS ESSENCIAIS
**Padrões de Design Mais Usados na Prática**
---
## ÍNDICE
1. [Padrões Criacionais](#1-padrões-criacionais)
2. [Padrões Estruturais](#2-padrões-estruturais)
3. [Padrões Comportamentais](#3-padrões-comportamentais)
4. [Padrões Arquiteturais](#4-padrões-arquiteturais)
5. [Anti-Patterns](#5-anti-patterns)
---
## 1. PADRÕES CRIACIONAIS
### 1.1) Singleton
```python
"""
SINGLETON: Garante que classe tenha apenas UMA instância.
Quando usar:
Configuration manager
Database connection pool
Logger
Cache global
Quando NÃO usar:
Estado compartilhado desnecessário
Dificulta testes
Geralmente um code smell
"""
class DatabaseConnection:
"""Singleton: Uma única conexão de database."""
_instance = None
_connection = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def connect(self, connection_string: str):
"""Conecta ao banco."""
if self._connection is None:
self._connection = create_connection(connection_string)
return self._connection
# Uso
db1 = DatabaseConnection()
db2 = DatabaseConnection()
assert db1 is db2 # Mesma instância!
# ALTERNATIVA MODERNA (Python): Module-level singleton
# [Link]
_connection = None
def get_connection(connection_string: str):
"""Singleton via module."""
global _connection
if _connection is None:
_connection = create_connection(connection_string)
return _connection
# Uso
from database import get_connection
conn = get_connection("postgresql://...")
1.2) Factory Method
"""
FACTORY METHOD: Delega criação de objetos para subclasses.
Quando usar:
Múltiplas implementações de interface
Criação complexa
Dependente de configuração
"""
from abc import ABC, abstractmethod
# Produto abstrato
class PaymentProcessor(ABC):
@abstractmethod
def process(self, amount: float) -> bool:
pass
# Produtos concretos
class CreditCardProcessor(PaymentProcessor):
def process(self, amount: float) -> bool:
print(f"Processing ${amount} via Credit Card")
return True
class PayPalProcessor(PaymentProcessor):
def process(self, amount: float) -> bool:
print(f"Processing ${amount} via PayPal")
return True
class PIXProcessor(PaymentProcessor):
def process(self, amount: float) -> bool:
print(f"Processing R${amount} via PIX")
return True
# Factory
class PaymentProcessorFactory:
"""Factory Method pattern."""
@staticmethod
def create(payment_method: str) -> PaymentProcessor:
"""Cria processor baseado em string."""
if payment_method == "credit_card":
return CreditCardProcessor()
elif payment_method == "paypal":
return PayPalProcessor()
elif payment_method == "pix":
return PIXProcessor()
else:
raise ValueError(f"Unknown payment method: {payment_method}")
# Uso
processor = [Link]("pix")
[Link](100.00) # PIX processor!
# VARIAÇÃO: Abstract Factory (família de objetos relacionados)
class UIFactory(ABC):
"""Abstract Factory para componentes UI."""
@abstractmethod
def create_button(self) -> 'Button':
pass
@abstractmethod
def create_checkbox(self) -> 'Checkbox':
pass
class WindowsUIFactory(UIFactory):
def create_button(self) -> 'Button':
return WindowsButton()
def create_checkbox(self) -> 'Checkbox':
return WindowsCheckbox()
class MacOSUIFactory(UIFactory):
def create_button(self) -> 'Button':
return MacOSButton()
def create_checkbox(self) -> 'Checkbox':
return MacOSCheckbox()
# Cliente usa factory sem saber implementação
def render_ui(factory: UIFactory):
button = factory.create_button()
checkbox = factory.create_checkbox()
[Link]()
[Link]()
1.3) Builder
"""
BUILDER: Constrói objetos complexos passo a passo.
Quando usar:
Objeto com muitos parâmetros opcionais
Construção em etapas
Múltiplas representações do mesmo objeto
"""
from dataclasses import dataclass
from typing import Optional
@dataclass
class Pizza:
"""Produto complexo."""
size: str
crust: str
cheese: bool = False
pepperoni: bool = False
mushrooms: bool = False
olives: bool = False
sauce: str = "tomato"
class PizzaBuilder:
"""Builder para Pizza."""
def __init__(self):
self._pizza = None
def reset(self):
"""Reseta builder."""
self._pizza = Pizza(size="medium", crust="regular")
return self
def set_size(self, size: str):
"""Define tamanho."""
self._pizza.size = size
return self # Fluent interface!
def set_crust(self, crust: str):
"""Define massa."""
self._pizza.crust = crust
return self
def add_cheese(self):
"""Adiciona queijo."""
self._pizza.cheese = True
return self
def add_pepperoni(self):
"""Adiciona pepperoni."""
self._pizza.pepperoni = True
return self
def add_mushrooms(self):
"""Adiciona cogumelos."""
self._pizza.mushrooms = True
return self
def set_sauce(self, sauce: str):
"""Define molho."""
self._pizza.sauce = sauce
return self
def build(self) -> Pizza:
"""Retorna pizza construída."""
pizza = self._pizza
[Link]() # Prepara para próxima pizza
return pizza
# Uso (Fluent Interface)
builder = PizzaBuilder()
pizza1 = (builder
.reset()
.set_size("large")
.set_crust("thin")
.add_cheese()
.add_pepperoni()
.add_mushrooms()
.build())
pizza2 = (builder
.reset()
.set_size("small")
.add_cheese()
.build())
# VARIAÇÃO: Director (encapsula construção comum)
class PizzaDirector:
"""Director para pizzas comuns."""
def __init__(self, builder: PizzaBuilder):
[Link] = builder
def make_margherita(self) -> Pizza:
"""Pizza Margherita pré-definida."""
return ([Link]
.reset()
.set_size("medium")
.add_cheese()
.set_sauce("tomato")
.build())
def make_pepperoni(self) -> Pizza:
"""Pizza Pepperoni pré-definida."""
return ([Link]
.reset()
.set_size("large")
.add_cheese()
.add_pepperoni()
.build())
director = PizzaDirector(PizzaBuilder())
margherita = director.make_margherita()
2. PADRÕES ESTRUTURAIS
2.1) Adapter
"""
ADAPTER: Converte interface de classe para outra esperada.
Quando usar:
Integração com código legado
API de terceiros incompatível
Múltiplas implementações com interfaces diferentes
"""
# Sistema legado
class LegacyPaymentSystem:
"""Sistema antigo com interface diferente."""
def make_payment(self, card_number: str, amount_cents: int):
"""Processa pagamento (valor em centavos)."""
print(f"Legacy: Processing {amount_cents} cents")
return {"success": True, "transaction_id": "12345"}
# Interface moderna esperada
class PaymentProcessor(ABC):
@abstractmethod
def process_payment(self, amount: float) -> str:
"""Processa pagamento (valor em reais)."""
pass
# Adapter
class LegacyPaymentAdapter(PaymentProcessor):
"""Adapta sistema legado para interface moderna."""
def __init__(self, legacy_system: LegacyPaymentSystem):
self.legacy_system = legacy_system
def process_payment(self, amount: float) -> str:
"""Implementa interface moderna."""
# Converte reais centavos
amount_cents = int(amount * 100)
# Chama sistema legado
result = self.legacy_system.make_payment(
card_number="****",
amount_cents=amount_cents
)
# Converte response
return result["transaction_id"]
# Uso
legacy = LegacyPaymentSystem()
adapter = LegacyPaymentAdapter(legacy)
# Cliente usa interface moderna
transaction_id = adapter.process_payment(100.50) # R$ 100.50
# EXEMPLO 2: Adapter para API externa
import requests
class StripeAdapter(PaymentProcessor):
"""Adapta Stripe API para nossa interface."""
def __init__(self, api_key: str):
self.api_key = api_key
def process_payment(self, amount: float) -> str:
"""Chama Stripe API."""
response = [Link](
"[Link]
auth=(self.api_key, ""),
data={
"amount": int(amount * 100), # Converte para centavos
"currency": "brl"
}
)
return [Link]()["id"]
2.2) Decorator
"""
DECORATOR: Adiciona responsabilidades a objetos dinamicamente.
Quando usar:
Adicionar funcionalidade sem modificar classe
Combinar funcionalidades flexivelmente
Single Responsibility Principle
"""
from abc import ABC, abstractmethod
from functools import wraps
import time
# Component
class Coffee(ABC):
@abstractmethod
def cost(self) -> float:
pass
@abstractmethod
def description(self) -> str:
pass
# Concrete Component
class SimpleCoffee(Coffee):
def cost(self) -> float:
return 5.0
def description(self) -> str:
return "Simple Coffee"
# Decorator Base
class CoffeeDecorator(Coffee):
def __init__(self, coffee: Coffee):
self._coffee = coffee
# Concrete Decorators
class MilkDecorator(CoffeeDecorator):
def cost(self) -> float:
return self._coffee.cost() + 2.0
def description(self) -> str:
return self._coffee.description() + ", Milk"
class SugarDecorator(CoffeeDecorator):
def cost(self) -> float:
return self._coffee.cost() + 0.5
def description(self) -> str:
return self._coffee.description() + ", Sugar"
class WhippedCreamDecorator(CoffeeDecorator):
def cost(self) -> float:
return self._coffee.cost() + 3.0
def description(self) -> str:
return self._coffee.description() + ", Whipped Cream"
# Uso (composição dinâmica!)
coffee = SimpleCoffee()
print(f"{[Link]()}: R$ {[Link]()}")
# Simple Coffee: R$ 5.0
coffee_with_milk = MilkDecorator(coffee)
print(f"{coffee_with_milk.description()}: R$ {coffee_with_milk.cost()}")
# Simple Coffee, Milk: R$ 7.0
fancy_coffee = WhippedCreamDecorator(
SugarDecorator(
MilkDecorator(SimpleCoffee())
)
)
print(f"{fancy_coffee.description()}: R$ {fancy_coffee.cost()}")
# Simple Coffee, Milk, Sugar, Whipped Cream: R$ 10.5
# PYTHON DECORATOR (função)
def timer(func):
"""Decorator de função: mede tempo de execução."""
@wraps(func)
def wrapper(*args, **kwargs):
start = [Link]()
result = func(*args, **kwargs)
end = [Link]()
print(f"{func.__name__} took {end - start:.2f}s")
return result
return wrapper
@timer
def slow_function():
[Link](2)
return "Done"
slow_function() # Imprime: slow_function took 2.00s
def retry(max_attempts: int = 3):
"""Decorator parametrizado: retry."""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}")
return wrapper
return decorator
@retry(max_attempts=3)
def unstable_function():
import random
if [Link]() < 0.7:
raise Exception("Random failure")
return "Success"
2.3) Facade
"""
FACADE: Interface simplificada para subsistema complexo.
Quando usar:
Simplificar API complexa
Desacoplar cliente de subsistemas
Criar ponto de entrada único
"""
# Subsistemas complexos
class ProductCatalog:
def check_availability(self, product_id: str) -> bool:
print(f"Checking availability of {product_id}")
return True
class InventorySystem:
def reserve(self, product_id: str, quantity: int):
print(f"Reserving {quantity} of {product_id}")
return f"reservation_{product_id}"
class PaymentGateway:
def process(self, amount: float) -> str:
print(f"Processing payment of ${amount}")
return "payment_123"
class ShippingService:
def schedule(self, address: str, items: list):
print(f"Scheduling shipment to {address}")
return "shipment_456"
class NotificationService:
def send_email(self, email: str, message: str):
print(f"Sending email to {email}")
# FACADE (simplifica interação)
class OrderFacade:
"""
Facade para processo de pedido.
Esconde complexidade de múltiplos subsistemas.
"""
def __init__(self):
[Link] = ProductCatalog()
[Link] = InventorySystem()
[Link] = PaymentGateway()
[Link] = ShippingService()
[Link] = NotificationService()
def place_order(
self,
product_id: str,
quantity: int,
payment_amount: float,
shipping_address: str,
customer_email: str
) -> dict:
"""
Método simples que coordena múltiplos subsistemas.
Cliente chama apenas 1 método!
"""
# 1. Verificar disponibilidade
if not [Link].check_availability(product_id):
return {"success": False, "error": "Product unavailable"}
# 2. Reservar estoque
reservation_id = [Link](product_id, quantity)
# 3. Processar pagamento
try:
payment_id = [Link](payment_amount)
except Exception:
# Rollback
[Link].cancel_reservation(reservation_id)
return {"success": False, "error": "Payment failed"}
# 4. Agendar envio
shipment_id = [Link](
shipping_address,
[{"product_id": product_id, "quantity": quantity}]
)
# 5. Notificar cliente
[Link].send_email(
customer_email,
f"Order confirmed! Shipment: {shipment_id}"
)
return {
"success": True,
"payment_id": payment_id,
"shipment_id": shipment_id
}
# Uso (cliente não precisa conhecer subsistemas!)
facade = OrderFacade()
result = facade.place_order(
product_id="NOTEBOOK-123",
quantity=1,
payment_amount=3000.0,
shipping_address="Rua A, 123",
customer_email="customer@[Link]"
)
# UMA chamada coordena 5 subsistemas!
3. PADRÕES COMPORTAMENTAIS
3.1) Strategy
"""
STRATEGY: Define família de algoritmos intercambiáveis.
Quando usar:
Múltiplos algoritmos para mesma tarefa
Evitar condicionais complexos (if/else)
Algoritmo pode mudar em runtime
"""
from abc import ABC, abstractmethod
# Strategy interface
class DiscountStrategy(ABC):
@abstractmethod
def calculate(self, amount: float) -> float:
"""Calcula desconto."""
pass
# Concrete Strategies
class NoDiscountStrategy(DiscountStrategy):
def calculate(self, amount: float) -> float:
return 0.0
class PercentageDiscountStrategy(DiscountStrategy):
def __init__(self, percentage: float):
[Link] = percentage
def calculate(self, amount: float) -> float:
return amount * ([Link] / 100)
class FixedDiscountStrategy(DiscountStrategy):
def __init__(self, discount_amount: float):
self.discount_amount = discount_amount
def calculate(self, amount: float) -> float:
return min(self.discount_amount, amount)
class VIPDiscountStrategy(DiscountStrategy):
"""Desconto especial: 20% + R$ 50."""
def calculate(self, amount: float) -> float:
percentage_discount = amount * 0.20
return percentage_discount + 50.0
# Context
class ShoppingCart:
def __init__(self, discount_strategy: DiscountStrategy):
[Link] = []
self.discount_strategy = discount_strategy
def add_item(self, price: float):
[Link](price)
def set_discount_strategy(self, strategy: DiscountStrategy):
"""Troca estratégia em runtime!"""
self.discount_strategy = strategy
def calculate_total(self) -> float:
subtotal = sum([Link])
discount = self.discount_strategy.calculate(subtotal)
return subtotal - discount
# Uso
cart = ShoppingCart(NoDiscountStrategy())
cart.add_item(100.0)
cart.add_item(50.0)
print(f"Total: R$ {cart.calculate_total()}") # R$ 150.00
# Troca estratégia dinamicamente
cart.set_discount_strategy(PercentageDiscountStrategy(10))
print(f"Total com 10% desconto: R$ {cart.calculate_total()}") # R$ 135.00
cart.set_discount_strategy(VIPDiscountStrategy())
print(f"Total VIP: R$ {cart.calculate_total()}") # R$ 70.00
3.2) Observer
"""
OBSERVER: Define dependência 1-para-N entre objetos.
Quando usar:
Mudança em um objeto deve notificar outros
Pub/Sub pattern
Event-driven architecture
"""
from abc import ABC, abstractmethod
from typing import List
# Observer interface
class Observer(ABC):
@abstractmethod
def update(self, subject: 'Subject') -> None:
pass
# Subject (Observable)
class Subject:
def __init__(self):
self._observers: List[Observer] = []
self._state = None
def attach(self, observer: Observer):
"""Registra observer."""
self._observers.append(observer)
def detach(self, observer: Observer):
"""Remove observer."""
self._observers.remove(observer)
def notify(self):
"""Notifica todos observers."""
for observer in self._observers:
[Link](self)
@property
def state(self):
return self._state
@[Link]
def state(self, value):
"""Quando estado muda, notifica observers."""
self._state = value
[Link]()
# Concrete Observers
class EmailObserver(Observer):
def update(self, subject: Subject):
print(f" EmailObserver: State changed to {[Link]}")
# Envia email
class SMSObserver(Observer):
def update(self, subject: Subject):
print(f" SMSObserver: State changed to {[Link]}")
# Envia SMS
class LogObserver(Observer):
def update(self, subject: Subject):
print(f" LogObserver: Logging state change to {[Link]}")
# Registra log
# Uso
subject = Subject()
# Registra observers
email_obs = EmailObserver()
sms_obs = SMSObserver()
log_obs = LogObserver()
[Link](email_obs)
[Link](sms_obs)
[Link](log_obs)
# Muda estado todos são notificados!
[Link] = "Order Created"
# EmailObserver: State changed to Order Created
# SMSObserver: State changed to Order Created
# LogObserver: Logging state change to Order Created
[Link] = "Payment Processed"
# Todos notificados novamente!
# EXEMPLO PRÁTICO: Event Bus
class EventBus:
"""Event bus simples usando Observer."""
def __init__(self):
self._subscribers = {}
def subscribe(self, event_type: str, callback: callable):
"""Registra callback para tipo de evento."""
if event_type not in self._subscribers:
self._subscribers[event_type] = []
self._subscribers[event_type].append(callback)
def publish(self, event_type: str, data: dict):
"""Publica evento."""
if event_type in self._subscribers:
for callback in self._subscribers[event_type]:
callback(data)
# Uso
event_bus = EventBus()
def send_welcome_email(data):
print(f"Sending welcome email to {data['email']}")
def create_user_profile(data):
print(f"Creating profile for {data['user_id']}")
def log_user_registration(data):
print(f"Logging registration: {data}")
# Registra handlers
event_bus.subscribe("user_registered", send_welcome_email)
event_bus.subscribe("user_registered", create_user_profile)
event_bus.subscribe("user_registered", log_user_registration)
# Publica evento todos handlers executam
event_bus.publish("user_registered", {
"user_id": "123",
"email": "user@[Link]"
})
3.3) Command
"""
COMMAND: Encapsula requisição como objeto.
Quando usar:
Undo/Redo
Queue de comandos
Transações
Macro recording
"""
from abc import ABC, abstractmethod
from typing import List
# Command interface
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
# Receiver
class TextEditor:
"""Receiver: objeto que executa ação."""
def __init__(self):
[Link] = ""
def insert(self, text: str, position: int):
[Link] = [Link][:position] + text + [Link][position:]
def delete(self, position: int, length: int):
[Link] = [Link][:position] + [Link][position + length:]
def __str__(self):
return [Link]
# Concrete Commands
class InsertCommand(Command):
def __init__(self, editor: TextEditor, text: str, position: int):
[Link] = editor
[Link] = text
[Link] = position
def execute(self):
[Link]([Link], [Link])
def undo(self):
[Link]([Link], len([Link]))
class DeleteCommand(Command):
def __init__(self, editor: TextEditor, position: int, length: int):
[Link] = editor
[Link] = position
[Link] = length
self.deleted_text = ""
def execute(self):
# Salva texto deletado para undo
self.deleted_text = [Link][
[Link]:[Link] + [Link]
]
[Link]([Link], [Link])
def undo(self):
[Link](self.deleted_text, [Link])
# Invoker
class CommandHistory:
"""Invoker: gerencia execução e histórico."""
def __init__(self):
[Link]: List[Command] = []
[Link] = -1
def execute(self, command: Command):
"""Executa comando e adiciona ao histórico."""
# Remove comandos após current (se houve undo)
[Link] = [Link][:[Link] + 1]
[Link]()
[Link](command)
[Link] += 1
def undo(self):
"""Desfaz último comando."""
if [Link] >= 0:
[Link][[Link]].undo()
[Link] -= 1
def redo(self):
"""Refaz comando desfeito."""
if [Link] < len([Link]) - 1:
[Link] += 1
[Link][[Link]].execute()
# Uso
editor = TextEditor()
history = CommandHistory()
# Executar comandos
[Link](InsertCommand(editor, "Hello", 0))
print(editor) # Hello
[Link](InsertCommand(editor, " World", 5))
print(editor) # Hello World
[Link](InsertCommand(editor, "!", 11))
print(editor) # Hello World!
# Undo
[Link]()
print(editor) # Hello World
[Link]()
print(editor) # Hello
# Redo
[Link]()
print(editor) # Hello World
4. PADRÕES ARQUITETURAIS
4.1) Repository Pattern
"""
REPOSITORY: Abstração para acesso a dados.
Benefícios:
Desacopla domínio de infraestrutura
Facilita testes
Centraliza lógica de queries
"""
from abc import ABC, abstractmethod
class UserRepository(ABC):
"""Interface do repositório."""
@abstractmethod
def save(self, user: User) -> None:
pass
@abstractmethod
def find_by_id(self, user_id: str) -> User | None:
pass
@abstractmethod
def find_by_email(self, email: str) -> User | None:
pass
# Implementação em memória (testes)
class InMemoryUserRepository(UserRepository):
def __init__(self):
[Link] = {}
def save(self, user: User) -> None:
[Link][[Link]] = user
def find_by_id(self, user_id: str) -> User | None:
return [Link](user_id)
def find_by_email(self, email: str) -> User | None:
for user in [Link]():
if [Link] == email:
return user
return None
# Implementação com SQLAlchemy (produção)
class SQLAlchemyUserRepository(UserRepository):
def __init__(self, session):
[Link] = session
def save(self, user: User) -> None:
orm_user = UserORM.from_domain(user)
[Link](orm_user)
[Link]()
def find_by_id(self, user_id: str) -> User | None:
orm_user = [Link](UserORM).get(user_id)
return orm_user.to_domain() if orm_user else None
4.2) Unit of Work
"""
UNIT OF WORK: Mantém lista de objetos modificados e coordena escrita.
Benefícios:
Transações consistentes
Minimiza acessos ao banco
Gerencia dependências entre objetos
"""
class UnitOfWork:
"""Unit of Work pattern."""
def __init__(self, session):
[Link] = session
[Link] = SQLAlchemyUserRepository(session)
[Link] = SQLAlchemyOrderRepository(session)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
[Link]()
else:
[Link]()
def commit(self):
"""Commit de todas mudanças."""
[Link]()
def rollback(self):
"""Rollback de todas mudanças."""
[Link]()
# Uso
with UnitOfWork(session) as uow:
# Múltiplas operações na mesma transação
user = [Link].find_by_id("123")
user.update_email("new@[Link]")
[Link](user)
order = [Link](user_id=[Link])
[Link](order)
# Commit automático ao sair do with (se sem exceção)
5. ANTI-PATTERNS
5.1) God Object
# ANTI-PATTERN: God Object
class OrderManager:
"""Faz TUDO relacionado a pedidos (ruim!)."""
def create_order(self, ...):
# Valida dados
# Verifica estoque
# Processa pagamento
# Envia email
# Atualiza analytics
# Gera relatório
# ...
pass
def cancel_order(self, ...):
pass
def calculate_shipping(self, ...):
pass
def send_notification(self, ...):
pass
def generate_invoice(self, ...):
pass
# 50+ métodos...
# SOLUÇÃO: Single Responsibility
class OrderService:
def __init__(
self,
inventory_service,
payment_service,
notification_service
):
[Link] = inventory_service
[Link] = payment_service
[Link] = notification_service
def create_order(self, ...):
# Coordena serviços especializados
[Link](...)
[Link](...)
[Link](...)
5.2) Spaghetti Code
# ANTI-PATTERN: Spaghetti Code
def process_order(order_data):
# Validação misturada com lógica de negócio
if not order_data.get("customer_id"):
return {"error": "No customer"}
# Acesso direto ao banco
customer = [Link](f"SELECT * FROM customers WHERE id={order_data['customer_id']}")
# Lógica complexa sem estrutura
total = 0
for item in order_data["items"]:
product = [Link](f"SELECT * FROM products WHERE id={item['id']}")
if product["stock"] < item["qty"]:
return {"error": "Out of stock"}
total += product["price"] * item["qty"]
# Chamada HTTP misturada
payment = [Link]("[Link] json={"amount": total})
# ... mais 200 linhas assim
# SOLUÇÃO: Separação de responsabilidades
class CreateOrderUseCase:
def __init__(self, order_repo, inventory_service, payment_service):
self.order_repo = order_repo
[Link] = inventory_service
[Link] = payment_service
def execute(self, request: CreateOrderRequest) -> CreateOrderResponse:
# Validação
self._validate(request)
# Lógica de negócio separada
order = [Link](...)
# Serviços especializados
[Link]([Link])
[Link]([Link])
# Persistência
self.order_repo.save(order)
return CreateOrderResponse(order_id=[Link])
📚 RECURSOS ADICIONAIS
Livro Clássico:
"Design Patterns: Elements of Reusable Object-Oriented Software" - Gang of Four (1994)
Livros Modernos:
"Head First Design Patterns" - Freeman & Freeman
"Refactoring to Patterns" - Joshua Kerievsky
Sites:
[Link]: [Link]
Source Making: [Link]