design_principles.md 5.4 KB

设计原则 (Design Principles)

本文档整理了面向对象设计的核心设计原则,并配以 Python 示例代码,旨在提高软件的可维护性、可复用性和灵活性。


1. 单一职责原则 (Single Responsibility Principle, SRP)

定义:一个类或模块应当有且只有一个引起它变化的原因。简单来说,一个类只负责一项职责。

好处

  • 降低类的复杂度。
  • 提高类的可读性和可维护性。
  • 降低变更引起的风险。

Python 示例

# 违反 SRP 的写法:一个类既负责统计又负责输出
class Report:
    def __init__(self, data):
        self.data = data

    def calculate_summary(self):
        return sum(self.data) / len(self.data)

    def export_pdf(self):
        print("Exporting to PDF...")

# 遵循 SRP 的写法:将统计和输出分离
class Report:
    def __init__(self, data):
        self.data = data

    def calculate_summary(self):
        return sum(self.data) / len(self.data)

class PDFExporter:
    def export(self, report):
        print(f"Exporting summary {report.calculate_summary()} to PDF...")

2. 开放-封闭原则 (Open-Closed Principle, OCP)

定义:软件实体(类、模块、函数等)应当对扩展开放,对修改封闭。即在不修改原有代码的基础上,通过扩展来增加新功能。

好处

  • 提高系统的可复用性。
  • 提高系统的可维护性。

Python 示例

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    def area(self):
        return 3.14 * (self.radius ** 2)

def calculate_total_area(shapes):
    return sum(shape.area() for shape in shapes)

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

定义:子类必须能够替换掉它们的父类,且程序的行为保持不变。

核心:子类不能违反父类定义的契约(协议)。

Python 示例

class Bird:
    def fly(self):
        print("Flying...")

class Sparrow(Bird):
    def fly(self):
        print("Sparrow flying...")

# 鸵鸟不会飞,如果强行继承 Bird 并重写 fly 抛错,则违反 LSP
class Ostrich(Bird):
    def fly(self):
        raise Exception("Ostrich cannot fly")

# 重构:将飞行的行为提取出来
class Bird(ABC):
    pass

class FlyingBird(Bird):
    def fly(self):
        print("Flying...")

class Sparrow(FlyingBird):
    pass

class Ostrich(Bird):
    pass

4. 依赖倒置原则 (Dependency Inversion Principle, DIP)

定义

  1. 高层模块不应依赖低层模块,两者都应依赖其抽象。
  2. 抽象不应依赖细节,细节应依赖抽象。

好处

  • 降低耦合度。
  • 增强系统的灵活性和可测试性。

Python 示例

from abc import ABC, abstractmethod

class MessageSender(ABC):
    @abstractmethod
    def send(self, message):
        pass

class EmailSender(MessageSender):
    def send(self, message):
        print(f"Sending email: {message}")

class NotificationService:
    def __init__(self, sender: MessageSender):
        self.sender = sender  # 依赖于抽象

    def notify(self, message):
        self.sender.send(message)

5. 接口隔离原则 (Interface Segregation Principle, ISP)

定义:不应该强迫客户端依赖于它们不使用的接口。接口应当尽量细化,一个类对另一个类的依赖应该建立在最小的接口上。

Python 示例

from abc import ABC, abstractmethod

# 违反 ISP:一个接口包含了所有动作
class Worker(ABC):
    @abstractmethod
    def work(self): pass
    @abstractmethod
    def eat(self): pass

# 遵循 ISP:拆分为更细的接口
class Workable(ABC):
    @abstractmethod
    def work(self): pass

class Eatable(ABC):
    @abstractmethod
    def eat(self): pass

class Robot(Workable):
    def work(self):
        print("Robot working...")

class Human(Workable, Eatable):
    def work(self):
        print("Human working...")
    def eat(self):
        print("Human eating...")

6. 合成/聚合复用原则 (Composite/Aggregate Reuse Principle, CARP)

定义:尽量使用组合(Composition)或聚合(Aggregation),少用继承(Inheritance)。

核心:继承会破坏封装性(白盒复用),而组合通过委托实现功能复用(黑盒复用),耦合度更低。

Python 示例

class Engine:
    def start(self):
        print("Engine starting...")

class Car:
    def __init__(self):
        self.engine = Engine() # 组合

    def start(self):
        print("Car starting...")
        self.engine.start()

7. 迪米特法则 (Law of Demeter, LoD / Least Knowledge Principle)

定义:一个对象应当对其他对象有尽可能少的了解。只与直接的朋友通信。

直接的朋友

  • 该对象本身。
  • 成员变量。
  • 方法参数。
  • 方法内创建的对象。

总结

这些设计原则(SOLID + CARP + LoD)是设计模式的基石。在实际开发中,应根据具体业务场景灵活应用,过度设计往往适得其反,核心目标是:高内聚、低耦合