🗒️Python中的SOLID原则
type
status
slug
summary
tags
category
icon
password
Date
SOLID原则:
S:单一职责原则(Single Responsibility Principle, SRP)。
O:开/闭原则(Open/Closed Principle, OCP)。
L:里氏替换原则(Liskov's Substitution Principle, LSP)。
I:接口分离原则(Interface Segregation Principle, ISP)
D:依赖倒置(反转)原则(Dependency Inversion Principle, DIP)
单一职责原则#
一个软件组件(通常是类)只能有一个职责,如果要修改这个类,那它的原因只能有一个。类越小越好
案例:
一个应用程序负责从数据源(可以是日志文件、数据库或众多其他的数据源)读取有关事件的信息,并根据事件确定要采取的措施
反例
存在的问题:
这个类定义了一个包含一系列方法的接口,但这些方法对应的操作是相互正交的:
每个操作都可以独立于其他操作完成,每个方法都表示类的一个职责,而每个职责都是导致类可能需要修改的原因。
正例:
将每个方法都放在不同的类中


可将单一职责作为一种思路,不需要在刚开始设计时就试图完全遵循它
开/闭原则#
软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的
案例:
需要设计一个监控系统,它对于另一个系统中发生的不同事件。能够根据以前收集的数据确定事件的类型
反例

预期行为
存在的问题
确定事件类型的逻辑集中放在一个大一统的方法中,每当需要在系统中新增事件类型时,都必须修改这个方法。这个方法并不是对修改关闭的。
我们希望能够在不修改这个方法(对修改关闭)的情况下添加新的事件类型,同时希望能够支持新的事件类型(对扩展开放),即添加新的事件时,只需添加代码,而无须修改既有的代码
正例:

在这个设计中,方法identify_event是关闭的:向域中添加新的事件类型时,无须修改它。相反,事件类层次结构对扩展是开放的:当新的事件类型出现在域中时,我们只需创建一个新类,并根据它实现的接口定义判断这种事件的标准
可扩展性
假设有新事件,来验证以上方式的可扩展性

可以看到只需要新增事件类
里氏替换原则#
LSP的原始定义(LISKOV 01)如下:如果S是T的子类型,则可将类型为T的对象替换为类型为S的对象,而不会破坏程序
案例
假设有一个客户端类,需要(包含)另一种类型的对象。通常,我们希望这个客户端与这种类型的对象交互,即通过接口进行工作


反例
正例
可以通过工具Mypy和Pylint作静态检查,找出这种不兼容的签名
接口分离原则#
拆分非常庞大臃肿的接口成为更小的和更具体的接口
反例
如果某个类不需要XML方法,它依然从接口获得了方法from_xml(),尽管不需要这个方法,却不得不保留它

正例
更佳的做法是,将这个接口分成两个,每个方法一个

依赖倒置原则#
是指一种特定的解耦(传统的依赖关系创建在高层次上,而具体的策略设置则应用在低层次的模块上)形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。
该原则规定:
高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口。
抽象接口不应该依赖于具体实现。而具体实现则应该依赖于抽象接口。
假设设计中有两个需要协作的对象——A和B。A使用B的实例,但我们的模块不能直接控制B(它可能是一个外部库或者是由另一个团队维护的模块)。如果代码严重依赖于B,一旦B发生变化,代码就将崩溃。为避免这种情况发生,必须倒置依赖,让B适应A。
案例
反例:图1,高层对象A依赖于底层对象B的实现;
正例:图2,把高层对象A对底层对象的需求抽象为一个接口A,底层对象B实现了接口A,这就是依赖反转。

参考#
Loading...