反模式与重构
学习设计模式后,重要的是知道何时不用,以及如何从糟糕的代码重构到优雅的设计。本章介绍常见的反模式和重构技巧。
常见反模式
反模式1:过度设计
# ❌ 反模式:简单的加法也用设计模式
class AddCommand:
"""加法命令"""
def __init__(self, x, y):
self.x = x
self.y = y
def execute(self):
return self.x + self.y
class CommandInvoker:
"""命令调用器"""
def __init__(self):
self._history = []
def execute_command(self, command):
result = command.execute()
self._history.append(command)
return result
class Calculator:
"""计算器"""
def __init__(self):
self.invoker = CommandInvoker()
def add(self, x, y):
command = AddCommand(x, y)
return self.invoker.execute_command(command)
# 使用
calc = Calculator()
result = calc.add(2, 3)
print(result) # 5
问题:简单的加法不需要命令模式!
✅ 重构后:
# ✅ 简单直接
def add(x, y):
"""加法函数"""
return x + y
# 使用
result = add(2, 3)
print(result) # 5
反模式2:金锤子
"当你有锤子时,所有问题都像钉子" - 只会使用某个模式,到处使用。
# ❌ 反模式:所有东西都做成单例
class User:
"""用户 - 单例?没必要!"""
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# 问题:系统可以有多个用户,不应该用单例
✅ 重构后:
# ✅ 普通类
class User:
"""用户"""
def __init__(self, name, email):
self.name = name
self.email = email
# 可以创建多个用户
user1 = User("Alice", "alice@example.com")
user2 = User("Bob", "bob@example.com")
反模式3:爆炸式子类
为了每个小变化都创建子类。
# ❌ 反模式:爆炸式子类
class Shape:
pass
class RedShape(Shape):
pass
class BlueShape(Shape):
pass
class GreenShape(Shape):
pass
class RedSquare(RedShape):
pass
class BlueSquare(BlueShape):
pass
class RedCircle(RedShape):
pass
class BlueCircle(BlueShape):
pass
# 问题:颜色和形状都是2种,就需要4个类
# 如果有10种颜色和10种形状,需要100个类!
✅ 重构后:使用组合
# ✅ 使用组合而非继承
class Shape:
"""形状"""
def __init__(self, color):
self.color = color
class Square(Shape):
"""正方形"""
def __init__(self, color, size):
super().__init__(color)
self.size = size
class Circle(Shape):
"""圆形"""
def __init__(self, color, radius):
super().__init__(color)
self.radius = radius
# 可以自由组合
red_square = Square("red", 10)
blue_circle = Circle("blue", 5)
green_circle = Circle("green", 3)
反模式4:上帝对象
一个类承担太多职责。
# ❌ 反模式:上帝对象
class GodObject:
"""上帝对象 - 做所有事情"""
def __init__(self):
self.users = []
self.orders = []
self.products = []
self.payments = []
self.shipments = []
self.notifications = []
self.reports = []
def add_user(self, user):
self.users.append(user)
def add_order(self, order):
self.orders.append(order)
def add_product(self, product):
self.products.append(product)
def process_payment(self, payment):
pass
def ship_order(self, order):
pass
def send_notification(self, message):
pass
def generate_report(self, report_type):
pass
# ... 更多方法
# 问题:一个类做太多事情,难以维护和测试
✅ 重构后:拆分职责
# ✅ 拆分成多个类,每个类只负责一件事
class UserManager:
"""用户管理"""
def __init__(self):
self.users = []
def add_user(self, user):
self.users.append(user)
class OrderManager:
"""订单管理"""
def __init__(self):
self.orders = []
def add_order(self, order):
self.orders.append(order)
class PaymentProcessor:
"""支付处理"""
def process_payment(self, payment):
pass
class NotificationService:
"""通知服务"""
def send_notification(self, message):
pass
反模式5:顺序依赖
执行顺序必须严格,但代码没有明确约束。
# ❌ 反模式:顺序依赖
class DataProcessor:
"""数据处理器"""
def __init__(self):
self.raw_data = None
self.cleaned_data = None
self.transformed_data = None
self.final_data = None
def load(self, data):
self.raw_data = data
def clean(self):
# 依赖load
self.cleaned_data = self.raw_data.strip()
def transform(self):
# 依赖clean
self.transformed_data = self.cleaned_data.upper()
def save(self):
# 依赖transform
self.final_data = self.transformed_data
# 问题:如果调用顺序错误,会导致错误
processor = DataProcessor()
processor.transform() # 报错!
✅ 重构后:模板方法模式
# ✅ 使用模板方法模式控制流程
class DataProcessor:
"""数据处理器"""
def process(self, raw_data):
"""模板方法 - 定义流程"""
print("开始处理数据...")
cleaned = self._clean(raw_data)
transformed = self._transform(cleaned)
saved = self._save(transformed)
print("处理完成!")
return saved
def _clean(self, data):
"""清洗数据"""
print("1. 清洗数据")
return data.strip()
def _transform(self, data):
"""转换数据"""
print("2. 转换数据")
return data.upper()
def _save(self, data):
"""保存数据"""
print("3. 保存数据")
return data
# 流程固定,无法错误调用
processor = DataProcessor()
result = processor.process(" hello world ")
重构技巧
技巧1:提取方法
# ❌ 之前:长方法
def process_order(order):
# 验证订单
if not order.customer_id:
raise ValueError("缺少客户ID")
if not order.items:
raise ValueError("订单为空")
if order.total <= 0:
raise ValueError("订单金额无效")
# 检查库存
for item in order.items:
if not check_stock(item.product_id, item.quantity):
raise ValueError(f"{item.product_id} 库存不足")
# 计算折扣
discount = 0
if order.customer_type == "VIP":
discount = 0.1
elif order.customer_type == "SVIP":
discount = 0.2
final_total = order.total * (1 - discount)
# 创建支付
payment = create_payment(final_total)
if payment.status != "success":
raise ValueError("支付失败")
# 更新库存
for item in order.items:
reduce_stock(item.product_id, item.quantity)
# 发送通知
send_notification(order.customer_id, "订单已确认")
return payment.transaction_id
# ✅ 重构后:提取方法
def process_order(order):
validate_order(order)
check_inventory(order)
total = calculate_total(order)
payment = process_payment(total)
update_inventory(order)
notify_customer(order)
return payment.transaction_id
def validate_order(order):
"""验证订单"""
if not order.customer_id:
raise ValueError("缺少客户ID")
if not order.items:
raise ValueError("订单为空")
if order.total <= 0:
raise ValueError("订单金额无效")
def check_inventory(order):
"""检查库存"""
for item in order.items:
if not check_stock(item.product_id, item.quantity):
raise ValueError(f"{item.product_id} 库存不足")
def calculate_total(order):
"""计算总价"""
discount = 0
if order.customer_type == "VIP":
discount = 0.1
elif order.customer_type == "SVIP":
discount = 0.2
return order.total * (1 - discount)
技巧2:用多态替代条件
# ❌ 之前:大量if-else
class PaymentProcessor:
def process(self, payment_type, amount):
if payment_type == "credit_card":
return self._process_credit_card(amount)
elif payment_type == "paypal":
return self._process_paypal(amount)
elif payment_type == "wechat":
return self._process_wechat(amount)
elif payment_type == "alipay":
return self._process_alipay(amount)
# ... 更多支付方式
def _process_credit_card(self, amount):
pass
def _process_paypal(self, amount):
pass
def _process_wechat(self, amount):
pass
def _process_alipay(self, amount):
pass
✅ 重构后:策略模式
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"信用卡支付: ${amount}")
return "CC-PAYMENT-ID"
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"PayPal支付: ${amount}")
return "PP-PAYMENT-ID"
class WeChatPayment(PaymentStrategy):
def pay(self, amount):
print(f"微信支付: ¥{amount}")
return "WX-PAYMENT-ID"
class PaymentProcessor:
def __init__(self, strategy: PaymentStrategy):
self.strategy = strategy
def process(self, amount):
return self.strategy.pay(amount)
# 使用 - 添加新支付方式无需修改现有代码
processor = PaymentProcessor(CreditCardPayment())
processor.process(100)
processor.strategy = WeChatPayment()
processor.process(500)
技巧3:提取类
# ❌ 之前:一个类做太多事
class OrderSystem:
def __init__(self):
self.orders = []
def create_order(self, customer_id, items):
order = {
"customer_id": customer_id,
"items": items,
"status": "pending"
}
self.orders.append(order)
return order
def send_email(self, email, subject, message):
import smtplib
# 发送邮件的逻辑...
print(f"发送邮件到 {email}: {subject}")
def send_sms(self, phone, message):
# 发送短信的逻辑...
print(f"发送短信到 {phone}: {message}")
def log(self, message):
# 记录日志的逻辑...
print(f"[LOG] {message}")
def save_to_database(self, data):
# 保存到数据库的逻辑...
print(f"保存数据: {data}")
✅ 重构后:提取类
class OrderManager:
"""订单管理"""
def __init__(self):
self.orders = []
def create_order(self, customer_id, items):
order = {
"customer_id": customer_id,
"items": items,
"status": "pending"
}
self.orders.append(order)
return order
class EmailService:
"""邮件服务"""
def send_email(self, email, subject, message):
print(f"发送邮件到 {email}: {subject}")
class SMSService:
"""短信服务"""
def send_sms(self, phone, message):
print(f"发送短信到 {phone}: {message}")
class Logger:
"""日志服务"""
def log(self, message):
print(f"[LOG] {message}")
class DatabaseService:
"""数据库服务"""
def save_to_database(self, data):
print(f"保存数据: {data}")
# 使用
order_manager = OrderManager()
email_service = EmailService()
sms_service = SMSService()
logger = Logger()
db_service = DatabaseService()
order = order_manager.create_order("customer1", [])
email_service.send_email("test@example.com", "订单确认", "您的订单已确认")
logger.log("订单已创建")
技巧4:用参数对象替代长参数列表
# ❌ 之前:长参数列表
def create_user(
name,
email,
age,
country,
city,
address,
phone,
preferences,
notifications,
privacy_settings
):
pass
# 使用时容易出错
create_user(
"Alice",
"alice@example.com",
30,
"China",
"Beijing",
"123 Main St",
"1234567890",
{"theme": "dark"},
{"email": True, "sms": False},
{"share_data": False}
)
✅ 重构后:参数对象
class UserProfile:
"""用户资料"""
def __init__(
self,
name,
email,
age=None,
country="",
city="",
address="",
phone="",
preferences=None,
notifications=None,
privacy_settings=None
):
self.name = name
self.email = email
self.age = age
self.country = country
self.city = city
self.address = address
self.phone = phone
self.preferences = preferences or {}
self.notifications = notifications or {}
self.privacy_settings = privacy_settings or {}
class UserBuilder:
"""用户建造者"""
def __init__(self, name, email):
self.profile = UserProfile(name, email)
def with_age(self, age):
self.profile.age = age
return self
def with_address(self, country, city, address):
self.profile.country = country
self.profile.city = city
self.profile.address = address
return self
def with_phone(self, phone):
self.profile.phone = phone
return self
def build(self):
return self.profile
# 使用
profile = (UserBuilder("Alice", "alice@example.com")
.with_age(30)
.with_address("China", "Beijing", "123 Main St")
.with_phone("1234567890")
.build())
def create_user(profile: UserProfile):
"""创建用户"""
print(f"创建用户: {profile.name}")
重构检查清单
在重构前,确保:
- [ ] 有自动化测试
- [ ] 理解代码的目的
- [ ] 确定重构范围
- [ ] 小步重构
- [ ] 每次重构后运行测试
- [ ] 保持代码可工作
本章要点
- ✅ 避免过度设计,简单问题用简单方案
- ✅ 避免"金锤子",根据需求选择模式
- ✅ 使用组合而非继承来避免爆炸式子类
- ✅ 拆分上帝对象,每个类只负责一件事
- ✅ 使用模板方法控制流程顺序
- ✅ 用多态替代条件
- ✅ 提取方法、提取类简化代码
- ✅ 使用参数对象替代长参数列表
- ✅ 重构前确保有测试
- ✅ 小步重构,持续验证
🎉 恭喜!你已完成《Python设计模式实战指南》的学习!
你已经掌握了: - ✅ 15种核心设计模式 - ✅ SOLID原则 - ✅ 模式对比与选择 - ✅ 实际项目应用 - ✅ 反模式与重构
继续实践,将这些模式应用到你的项目中!🚀