PythonSOLID原则实践

PythonSOLID原则实践 Python SOLID 原则实践SOLID 是面向对象设计的五大原则能让代码更易维护、扩展和测试。本文用 Python 示例逐一讲解。1. 单一职责原则 (Single Responsibility Principle)---------------------------------------------------一个类应该只有一个引起变化的原因即只负责一项职责。class ReportGenerator:只负责生成报告——单一职责def generate(self, data: dict) - str:# 将数据格式化为报告字符串report_lines [f报告标题: {data.get(title, 无标题)}]report_lines.append(f作者: {data.get(author, 未知)})for key, value in data.get(items, {}).items():report_lines.append(f {key}: {value})return \n.join(report_lines)class ReportSaver:只负责保存报告——单一职责与 ReportGenerator 分离def save(self, report: str, path: str) - None:with open(path, w, encodingutf-8) as f:f.write(report)# 错误示范一个类既生成又保存又发送三个变化原因class BadReport:def generate(self, data): ...def save(self, path): ...def send_email(self, recipient): ...2. 开闭原则 (Open/Closed Principle)-------------------------------------对扩展开放对修改关闭。通过继承或组合增加新行为。from abc import ABC, abstractmethodclass DiscountStrategy(ABC):折扣策略抽象基类——对扩展开放abstractmethoddef apply(self, price: float) - float: ...class NoDiscount(DiscountStrategy):def apply(self, price: float) - float:return priceclass PercentageDiscount(DiscountStrategy):def __init__(self, percent: float):self.percent percentdef apply(self, price: float) - float:return price * (1 - self.percent / 100)class Order:订单类——对修改关闭不需要因为新折扣类型而修改def __init__(self, price: float, strategy: DiscountStrategy):self.price priceself.strategy strategydef final_price(self) - float:return self.strategy.apply(self.price)# 新增会员折扣无需修改 Order——只需新增策略类class MemberDiscount(DiscountStrategy):def __init__(self, level: str):self.level leveldef apply(self, price: float) - float:ratios {gold: 0.7, silver: 0.85, bronze: 0.95}return price * ratios.get(self.level, 1.0)3. 里氏替换原则 (Liskov Substitution Principle)-------------------------------------------------子类必须能替换父类而不破坏程序正确性。class Rectangle:矩形基类def __init__(self, width: int, height: int):self.width widthself.height heightdef area(self) - int:return self.width * self.heightclass Square(Rectangle):正方形——违反 LSP设 width 会改变 height反之亦然def __init__(self, side: int):super().__init__(side, side)# 问题Square 重设 width 也会改变 height违反父类契约propertydef width(self):return self._widthwidth.setterdef width(self, value):self._width valueself._height value # 副作用违反 LSPpropertydef height(self):return self._heightheight.setterdef height(self, value):self._height valueself._width value # 副作用违反 LSP# 更好的做法使用独立接口不强制继承关系class Shape(ABC):abstractmethoddef area(self) - int: ...class ProperSquare(Shape):不继承 Rectangle直接实现 Shape避免 LSP 违规def __init__(self, side: int):self.side sidedef area(self) - int:return self.side * self.side4. 接口隔离原则 (Interface Segregation Principle)---------------------------------------------------客户端不应被迫依赖它们不使用的接口。用小型专注的协议替代庞大接口。from typing import Protocolclass Printer(Protocol):小型专注协议只负责打印def print_document(self, doc: str) - None: ...class Scanner(Protocol):小型专注协议只负责扫描def scan_document(self) - str: ...class SimplePrinter:只实现了 Printer不需要扫描功能def print_document(self, doc: str) - None:print(f打印: {doc})class MultiFunctionDevice:需要多个功能时才组合多个协议def print_document(self, doc: str) - None:print(f打印: {doc})def scan_document(self) - str:return 扫描结果5. 依赖反转原则 (Dependency Inversion Principle)---------------------------------------------------高层模块不应依赖低层模块二者都应依赖抽象。class EmailSender(ABC):抽象发送器接口abstractmethoddef send(self, message: str, to: str) - None: ...class SmtpEmailSender(EmailSender):低层模块具体实现def send(self, message: str, to: str) - None:print(f通过 SMTP 发送 {message} 到 {to})class NotificationService:高层模块依赖抽象而非具体实现def __init__(self, sender: EmailSender): # 注入抽象self.sender senderdef notify(self, user_email: str, msg: str) - None:self.sender.send(msg, user_email)# 使用依赖注入轻松切换实现smtp SmtpEmailSender()service NotificationService(smtp)service.notify(aliceexample.com, 订单已确认)总结SOLID 原则指导我们写出高内聚低耦合的代码。单一职责让类更聚焦开闭原则让扩展更容易里氏替换保证继承安全接口隔离避免臃肿接口依赖反转降低模块间耦合。实践中不必教条合理运用即可。