from abc import ABC, abstractmethod from typing import List, Protocol """ Lec 3: 设计原则 (Design Principles) 这些代码示例展示了 SOLID 原则及其他核心设计原则在 Python 中的实现。 """ # ----------------------------------------------------------------------------- # 1. 单一职责原则 (Single Responsibility Principle, SRP) # ----------------------------------------------------------------------------- class Report: """负责数据逻辑的类""" def __init__(self, data: List[float]): self.data = data def calculate_summary(self) -> float: return sum(self.data) / len(self.data) if self.data else 0.0 class PDFExporter: """负责 PDF 导出的类""" def export(self, report: Report, filepath: str): summary = report.calculate_summary() print(f"[PDF] 导出摘要: {summary} 到文件: {filepath}") class HTMLExporter: """负责 HTML 导出的类""" def export(self, report: Report, filepath: str): summary = report.calculate_summary() print(f"[HTML] 导出摘要: {summary} 到文件: {filepath}") # ----------------------------------------------------------------------------- # 2. 开放-封闭原则 (Open-Closed Principle, OCP) # ----------------------------------------------------------------------------- class Shape(ABC): @abstractmethod def area(self) -> float: pass class Rectangle(Shape): def __init__(self, width: float, height: float): self.width = width self.height = height def area(self) -> float: return self.width * self.height class Circle(Shape): def __init__(self, radius: float): self.radius = radius def area(self) -> float: import math return math.pi * (self.radius ** 2) def print_areas(shapes: List[Shape]): """对扩展开放:可以添加新形状而无需修改此函数""" for shape in shapes: print(f"Shape area: {shape.area()}") # ----------------------------------------------------------------------------- # 3. 里氏替换原则 (Liskov Substitution Principle, LSP) # ----------------------------------------------------------------------------- class Bird(ABC): pass class FlyingBird(Bird): @abstractmethod def fly(self): pass class NonFlyingBird(Bird): pass class Sparrow(FlyingBird): def fly(self): print("麻雀正在飞翔...") class Ostrich(NonFlyingBird): def run(self): print("鸵鸟正在奔跑...") # ----------------------------------------------------------------------------- # 4. 依赖倒置原则 (Dependency Inversion Principle, DIP) # ----------------------------------------------------------------------------- class MessageSender(ABC): @abstractmethod def send(self, message: str): pass class EmailSender(MessageSender): def send(self, message: str): print(f"发送邮件通知: {message}") class SMSSender(MessageSender): def send(self, message: str): print(f"发送短信通知: {message}") class NotificationService: def __init__(self, sender: MessageSender): # 依赖于抽象接口 MessageSender,而不是具体的 EmailSender 或 SMSSender self.sender = sender def notify(self, message: str): self.sender.send(message) # ----------------------------------------------------------------------------- # 5. 接口隔离原则 (Interface Segregation Principle, ISP) # ----------------------------------------------------------------------------- class Workable(Protocol): def work(self) -> None: ... class Eatable(Protocol): def eat(self) -> None: ... class Human(Workable, Eatable): def work(self) -> None: print("人类在工作...") def eat(self) -> None: print("人类在吃饭...") class Robot(Workable): def work(self) -> None: print("机器人在工作...") # ----------------------------------------------------------------------------- # 6. 合成/聚合复用原则 (Composite/Aggregate Reuse Principle, CARP) # ----------------------------------------------------------------------------- class Engine: def start(self): print("发动机已启动") class Car: def __init__(self, engine: Engine): # 使用组合而非继承 self.engine = engine def start(self): print("汽车准备出发...") self.engine.start() # ----------------------------------------------------------------------------- # 7. 迪米特法则 (Law of Demeter, LoD) # ----------------------------------------------------------------------------- class Teacher: def command(self, group_leader): # 老师只下令给组长,不直接接触学生 group_leader.count_students() class GroupLeader: def __init__(self, students): self.students = students def count_students(self): print(f"学生总人数: {len(self.students)}") # ----------------------------------------------------------------------------- # 演示运行 # ----------------------------------------------------------------------------- if __name__ == "__main__": print("--- SRP ---") my_report = Report([10.5, 20.0, 15.5]) pdf_exp = PDFExporter() pdf_exp.export(my_report, "data.pdf") print("\n--- OCP ---") shapes = [Rectangle(10, 5), Circle(7)] print_areas(shapes) print("\n--- LSP ---") sparrow = Sparrow() sparrow.fly() print("\n--- DIP ---") service = NotificationService(SMSSender()) service.notify("您有一条新消息") print("\n--- ISP ---") worker = Robot() worker.work() print("\n--- CARP ---") engine = Engine() my_car = Car(engine) my_car.start() print("\n--- LoD ---") students = ["Alice", "Bob", "Charlie"] leader = GroupLeader(students) teacher = Teacher() teacher.command(leader)