I'll show you the Strategy Pattern, which is extensively used in Python, particularly in sorting algorithms and payment processing systems.
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List
from decimal import Decimal
# Data structures
@dataclass
class Item:
name: str
price: Decimal
quantity: int
@dataclass
class Order:
items: List[Item]
shipping_address: str
@property
def total(self) -> Decimal:
return sum(item.price * item.quantity for item in self.items)
# Strategy Interface
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount: Decimal) -> bool:
pass
@abstractmethod
def validate(self) -> bool:
pass
# Concrete Strategy Implementations
class CreditCardPayment(PaymentStrategy):
def __init__(self, card_number: str, expiry: str, cvv: str):
self.card_number = card_number
self.expiry = expiry
self.cvv = cvv
def validate(self) -> bool:
# Basic credit card validation
if len(self.card_number) not in [15, 16]:
return False
if not self.card_number.isdigit():
return False
if not self.cvv.isdigit() or len(self.cvv) not in [3, 4]:
return False
return True
def pay(self, amount: Decimal) -> bool:
if not self.validate():
raise ValueError("Invalid credit card details")
print(f"Processing credit card payment of ${amount}")
# Here you would integrate with a real payment gateway
return True
class PayPalPayment(PaymentStrategy):
def __init__(self, email: str, password: str):
self.email = email
self.password = password
def validate(self) -> bool:
# Basic PayPal validation
return '@' in self.email and len(self.password) >= 8
def pay(self, amount: Decimal) -> bool:
if not self.validate():
raise ValueError("Invalid PayPal credentials")
print(f"Processing PayPal payment of ${amount}")
# Here you would integrate with PayPal's API
return True
class CryptoPayment(PaymentStrategy):
def __init__(self, wallet_address: str, network: str):
self.wallet_address = wallet_address
self.network = network
def validate(self) -> bool:
# Basic crypto wallet validation
return len(self.wallet_address) == 42 and self.wallet_address.startswith('0x')
def pay(self, amount: Decimal) -> bool:
if not self.validate():
raise ValueError("Invalid wallet address")
print(f"Processing crypto payment of ${amount} on {self.network} network")
# Here you would integrate with blockchain
return True
# Context class that uses the strategy
class PaymentProcessor:
def __init__(self, payment_strategy: PaymentStrategy = None):
self.payment_strategy = payment_strategy
def set_strategy(self, payment_strategy: PaymentStrategy):
self.payment_strategy = payment_strategy
def process_payment(self, order: Order) -> bool:
if not self.payment_strategy:
raise ValueError("Payment strategy not set")
return self.payment_strategy.pay(order.total)
# Example usage
def main():
# Create sample order
items = [
Item("Laptop", Decimal("999.99"), 1),
Item("Mouse", Decimal("24.99"), 2)
]
order = Order(items, "123 Main St, City, Country")
# Initialize payment processor
processor = PaymentProcessor()
# Process with credit card
try:
cc_strategy = CreditCardPayment(
card_number="4111111111111111",
expiry="12/24",
cvv="123"
)
processor.set_strategy(cc_strategy)
processor.process_payment(order)
except ValueError as e:
print(f"Credit card payment failed: {e}")
# Process with PayPal
try:
paypal_strategy = PayPalPayment(
email="[email protected]",
password="secure_password123"
)
processor.set_strategy(paypal_strategy)
processor.process_payment(order)
except ValueError as e:
print(f"PayPal payment failed: {e}")
# Process with Crypto
try:
crypto_strategy = CryptoPayment(
wallet_address="0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
network="Ethereum"
)
processor.set_strategy(crypto_strategy)
processor.process_payment(order)
except ValueError as e:
print(f"Crypto payment failed: {e}")
if __name__ == "__main__":
main()
The Strategy Pattern is widely used in Python's standard library and real-world applications. Here's why it's important:
sorted()
function accepts a key
parameter as a strategyExample from Python's standard library:
# Different sorting strategies using the same interface
names = ['John', 'Alice', 'Bob']
sorted(names, key=str.lower) # Strategy: lowercase comparison
sorted(names, key=len) # Strategy: length comparison
Would you like me to: