面向对象SOLID设计

单一职责原则(SRP)(Single responsibility principle)

原则

  • SRP 原则认为:一个类只应该有一种被修改的原因
  • 编写更小的类通常更不容易违反 SRP 原则
  • SRP 原则同样适用于函数,你可以让函数和类协同工作

实现方法

  • 将一个含有多个方法的类分成多个不同的类

开放——关闭原则(OCP)(Open–closed principle)

原则

  • OCP 原则认为:类应该对改动关闭,对扩展开放
  • 通过分析需求,找到代码中易变的部分,是让类符合 OCP 原则的关键

实现方法

  • 使用子类继承的方式可以让类符合 OCP 原则
  • 通过算法类与依赖注入,也可以让类符合 OCP 原则
  • 将数据与逻辑分离,使用数据驱动的方式也是符合 OCP 原则的好办法

里氏替换原则 (Liskov Substitution Principle)

“里氏替换原则”是一个非常具体的原则,它专门为 OOP 里的继承场景服务。当你设计类继承关系,尤其是编写子类代码时,请经常性的问自己这个问题:“如果我把项目里所有使用父类的地方换成这个子类,程序是否还能正常运行?”

如果答案是否定的,那么你就应该考虑调整一下现在的类设计了。调整方式有很多种,有时候你得把大类拆分为更小的类,有时候你得调换类之间的继承关系,有时候你得为父类添加新的方法和属性,就像文章里的第一个场景一样。

  • “L:里氏替换原则” 认为子类应该可以任意替换父类被使用
  • 在类的使用方增加具体的类型判断(isinstance),通常不是最佳解决方案
  • 违反里氏替换原则,通常也会导致违反“开放-关闭”原则
  • 考虑什么是类的核心特征,然后为父类增加新的方法和属性可以帮到你
  • 子类方法应该和父类同名方法返回同一类型,或者返回支持更多操作的子类型也行
  • 子类的方法参数应该和父类同名方法完全一致,或者更为宽松(子类可以为方法增加额外的可选参数:如active_only = True // war = None )。

依赖倒置原则(Dependency Inversion Principle)

就是一条和依赖关系相关的原则。它认为:“高层模块不应该依赖于低层模块,二者都应该依赖于抽象。”

  • “D:依赖倒置原则” 认为高层模块和低层模块都应该依赖于抽象
  • 依赖抽象,意味着我们可以完全修改低层实现,而不影响高层代码
  • 在 Python 中你可以使用 abc 模块来定义抽象类
  • 除 abc 外,你也可以使用其他技术来完成依赖倒置

接口隔离原则(Interface Segregation Principles)

在 I 原则看来,一个接口所提供的方法,应该就是使用方所需要的方法,不多不少刚刚好。

  • “I:接口隔离原则” 认为客户不应该依赖任何它不使用的方法
  • 设计接口就是设计抽象
  • 违反接口隔离原则也可能会导致违反单一职责与里式替换原则
  • 写更小的类、写更小的接口在大多数情况下是个好主意