lec3_design_principle.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. from abc import ABC, abstractmethod
  2. from typing import List, Protocol
  3. """
  4. Lec 3: 设计原则 (Design Principles)
  5. 这些代码示例展示了 SOLID 原则及其他核心设计原则在 Python 中的实现。
  6. """
  7. # -----------------------------------------------------------------------------
  8. # 1. 单一职责原则 (Single Responsibility Principle, SRP)
  9. # -----------------------------------------------------------------------------
  10. class Report:
  11. """负责数据逻辑的类"""
  12. def __init__(self, data: List[float]):
  13. self.data = data
  14. def calculate_summary(self) -> float:
  15. return sum(self.data) / len(self.data) if self.data else 0.0
  16. class PDFExporter:
  17. """负责 PDF 导出的类"""
  18. def export(self, report: Report, filepath: str):
  19. summary = report.calculate_summary()
  20. print(f"[PDF] 导出摘要: {summary} 到文件: {filepath}")
  21. class HTMLExporter:
  22. """负责 HTML 导出的类"""
  23. def export(self, report: Report, filepath: str):
  24. summary = report.calculate_summary()
  25. print(f"[HTML] 导出摘要: {summary} 到文件: {filepath}")
  26. # -----------------------------------------------------------------------------
  27. # 2. 开放-封闭原则 (Open-Closed Principle, OCP)
  28. # -----------------------------------------------------------------------------
  29. class Shape(ABC):
  30. @abstractmethod
  31. def area(self) -> float:
  32. pass
  33. class Rectangle(Shape):
  34. def __init__(self, width: float, height: float):
  35. self.width = width
  36. self.height = height
  37. def area(self) -> float:
  38. return self.width * self.height
  39. class Circle(Shape):
  40. def __init__(self, radius: float):
  41. self.radius = radius
  42. def area(self) -> float:
  43. import math
  44. return math.pi * (self.radius ** 2)
  45. def print_areas(shapes: List[Shape]):
  46. """对扩展开放:可以添加新形状而无需修改此函数"""
  47. for shape in shapes:
  48. print(f"Shape area: {shape.area()}")
  49. # -----------------------------------------------------------------------------
  50. # 3. 里氏替换原则 (Liskov Substitution Principle, LSP)
  51. # -----------------------------------------------------------------------------
  52. class Bird(ABC):
  53. pass
  54. class FlyingBird(Bird):
  55. @abstractmethod
  56. def fly(self):
  57. pass
  58. class NonFlyingBird(Bird):
  59. pass
  60. class Sparrow(FlyingBird):
  61. def fly(self):
  62. print("麻雀正在飞翔...")
  63. class Ostrich(NonFlyingBird):
  64. def run(self):
  65. print("鸵鸟正在奔跑...")
  66. # -----------------------------------------------------------------------------
  67. # 4. 依赖倒置原则 (Dependency Inversion Principle, DIP)
  68. # -----------------------------------------------------------------------------
  69. class MessageSender(ABC):
  70. @abstractmethod
  71. def send(self, message: str):
  72. pass
  73. class EmailSender(MessageSender):
  74. def send(self, message: str):
  75. print(f"发送邮件通知: {message}")
  76. class SMSSender(MessageSender):
  77. def send(self, message: str):
  78. print(f"发送短信通知: {message}")
  79. class NotificationService:
  80. def __init__(self, sender: MessageSender):
  81. # 依赖于抽象接口 MessageSender,而不是具体的 EmailSender 或 SMSSender
  82. self.sender = sender
  83. def notify(self, message: str):
  84. self.sender.send(message)
  85. # -----------------------------------------------------------------------------
  86. # 5. 接口隔离原则 (Interface Segregation Principle, ISP)
  87. # -----------------------------------------------------------------------------
  88. class Workable(Protocol):
  89. def work(self) -> None: ...
  90. class Eatable(Protocol):
  91. def eat(self) -> None: ...
  92. class Human(Workable, Eatable):
  93. def work(self) -> None:
  94. print("人类在工作...")
  95. def eat(self) -> None:
  96. print("人类在吃饭...")
  97. class Robot(Workable):
  98. def work(self) -> None:
  99. print("机器人在工作...")
  100. # -----------------------------------------------------------------------------
  101. # 6. 合成/聚合复用原则 (Composite/Aggregate Reuse Principle, CARP)
  102. # -----------------------------------------------------------------------------
  103. class Engine:
  104. def start(self):
  105. print("发动机已启动")
  106. class Car:
  107. def __init__(self, engine: Engine):
  108. # 使用组合而非继承
  109. self.engine = engine
  110. def start(self):
  111. print("汽车准备出发...")
  112. self.engine.start()
  113. # -----------------------------------------------------------------------------
  114. # 7. 迪米特法则 (Law of Demeter, LoD)
  115. # -----------------------------------------------------------------------------
  116. class Teacher:
  117. def command(self, group_leader):
  118. # 老师只下令给组长,不直接接触学生
  119. group_leader.count_students()
  120. class GroupLeader:
  121. def __init__(self, students):
  122. self.students = students
  123. def count_students(self):
  124. print(f"学生总人数: {len(self.students)}")
  125. # -----------------------------------------------------------------------------
  126. # 演示运行
  127. # -----------------------------------------------------------------------------
  128. if __name__ == "__main__":
  129. print("--- SRP ---")
  130. my_report = Report([10.5, 20.0, 15.5])
  131. pdf_exp = PDFExporter()
  132. pdf_exp.export(my_report, "data.pdf")
  133. print("\n--- OCP ---")
  134. shapes = [Rectangle(10, 5), Circle(7)]
  135. print_areas(shapes)
  136. print("\n--- LSP ---")
  137. sparrow = Sparrow()
  138. sparrow.fly()
  139. print("\n--- DIP ---")
  140. service = NotificationService(SMSSender())
  141. service.notify("您有一条新消息")
  142. print("\n--- ISP ---")
  143. worker = Robot()
  144. worker.work()
  145. print("\n--- CARP ---")
  146. engine = Engine()
  147. my_car = Car(engine)
  148. my_car.start()
  149. print("\n--- LoD ---")
  150. students = ["Alice", "Bob", "Charlie"]
  151. leader = GroupLeader(students)
  152. teacher = Teacher()
  153. teacher.command(leader)