单一职责原则(Single Responsibility Principle,SRP)
描述
There should never be more than one reason for a class to change。仅有一种原因引起类的改变。一个类只负责一个职责
特点
- 一个类负责一个单一职责,避免职责上的交叉实现
- 保证面向接口实现
参考
SRP
开放封闭原则(Open Closed Principle,OCP)
描述
新需求来临时,通过新增类实现,而不是修改已有类
特点
- 开放:对于扩展开放;封闭:对于更改封闭
- 任何类都不应该从具体类派生
- 代码实现初期,尽量抽象代码以隔绝变化
- 代码实现中期,尽量不改变已有代码,而是增加新的代码面对变化
参考
OCP
里氏替换原则(Liskov Substitution Principle,LSP)
描述
父类能出现的地方,可以直接用其子类替代
实现标准
-
子类必须完全实现父类的抽象方法,但不能覆盖父类的非抽象方法
-
子类可以实现自己特有的方法
-
当子类覆盖或实现父类的方法时,方法的前置条件(输入形参)要比父类方法的输入更宽松
即父类接受参数类型为xx,则子类的参数类型应该比父类更宽松,可以是xx也可以是yy,即子类可以处理更多类型的输入参数
-
当子类的方法实现父类的抽象方法时,方法的后置条件(返回值)要比父类更加严格
即父类的返回值类型为xx,则子类的返回值类型应该比父类更严格,可以是xx,或者是xx的子类,即子类的返回值类型需要更加具体,返回的结果应该是父类返回结果的子类
参考
后边再找
接口分离原则(Interface Segregation Principle,ISP)
描述
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖哪些他不需要的接口
实现标准
- 每个类尽量提供接口或者抽象类,或者两者都具备
- 变量的声明类型尽量是接口或者抽象类
- 任何类都不应该从具体类派生
- 使用继承时尽量遵循里氏替换原则
参考
ISP
依赖倒置原则(Dependency Inversion Principle,DIP)
描述
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象
- 核心思想:要面向接口变成,而不是面向实现编程
实例
from abc import ABC, abstractmethod# 定义一个抽象类作为低层模块的抽象
class DataStorage(ABC):@abstractmethoddef read_data(self):pass@abstractmethoddef write_data(self, data):pass# 低层模块的具体实现
class FileStorage(DataStorage):def read_data(self):print("Reading data from file")# 具体的读取文件的实现def write_data(self, data):print("Writing data to file")# 具体的写入文件的实现# 高层模块依赖于低层模块的抽象接口
class DataManager:def __init__(self, storage: DataStorage):self.storage = storagedef process_data(self):data = self.storage.read_data()# 对数据进行处理processed_data = self._process_data(data)self.storage.write_data(processed_data)def _process_data(self, data):# 数据处理的具体实现pass# 创建低层模块的实例
file_storage = FileStorage()# 创建高层模块的实例,并传入低层模块的实例
data_manager = DataManager(file_storage)# 调用高层模块的方法进行数据处理
data_manager.process_data()
通过这样的设计,高层模块
DataManager
不依赖于低层模块FileStorage
的具体实现,而是依赖于抽象接口DataStorage
最少知识原则(Least Knowledge Principle,LKP)
描述
- 从依赖者角度,只依赖应该依赖的对象
- 从被依赖者角度,只暴漏应该暴漏的方法
优点
- 降低了类之间的耦合度,提高了模块的相对独立性
- 由于亲和度降低,从而提高了类的可复用率和系统的扩展性
参考
LKP