【程序杂谈】设计模式的基石——软件开发原则| 青训营笔记

53 阅读5分钟

这是我参与「第四届青训营 」笔记创作活动的第6天

昨天我们简单聊了聊JavaScript中常用的设计模式,今天接着这个话题,我们来看一看设计模式的基石——软件开发原则

软件开发原则

软件开发原则是一些程序员大牛在实践中通过凝练和总结经验得到的一些基本性的开发准则,用于避免一些影响程序可维护性问题的出现。建立在这些软件开发原则的基础上,形成了诸多的设计模式,指导着程序员们的开发。发展至今,软件开发原则大致可以分为7大原则,分别是:

  • 开闭原则OCP
  • 依赖倒置原则DIP
  • 单一职责原则SRP
  • 里式替换原则LSP
  • 接口隔离原则ISP
  • 迪米特法则LoD/最少知道原则LKP
  • 合成/聚合复用原则CARP

下面将一一介绍这些软件开发原则的具体含义。

开闭原则OCP

开闭原则指的是,一个程序,应该对扩展开放,而对修改关闭,面向对象设计就是开闭原则的体现。

例如我们使用抽象类构建程序框架,我们可以在框架上进行扩展实现具体的功能细节,但是尽可能少的去改动原有的代码,这就是开闭原则在的核心思想。

优点

  • 使系统更加灵活、可拓展
  • 提高代码的复用率
  • 使软件易于维护性

依赖倒置原则DIP

依赖倒置原则的定义是:

  • 高层模块不应依赖底层模块,二者都应依赖其抽象
  • 抽象模块不应依赖于细节,而是细节依赖于抽象
  • 面向接口编程,而不是面向实现编程

依赖倒置原则的定义听起来似乎就没有开闭原则那么简洁易懂了,其实它就是在强调一个接口的概念。我们的逻辑实现可以分为最基本的底层模块(抽象类、接口等)和底层模块组装起来的高层模块(实现类),DIP就要求我们实现:

  • 类之间不要进行之间的依赖,而是从底层模块产生依赖关系
  • 接口和抽象类不要依赖于实现类
  • 通过接口声明依赖

优点

  • 降低类之间的耦合性
  • 提高代码的可读性和可维护性
  • 降低变更代码带来的风险

单一职责原则SRP

单一职责原则很好理解,就是一个类、接口、函数方法就只专门负责一项职责,这样在某个业务逻辑需要发生变更时就不会影响到其他业务逻辑的正常工作。

单一职责原则定义看起来很简单,但是在具体实现过程中往往会因为项目规模太大,各种依赖、组合关系过于繁杂,很难实现完全的单一职责。所以在开发的过程中,我们就要时刻注意接口和方法的编写,尽量保持单一职责。

优点

  • 降低类的复杂度
  • 提高代码的可读性和可维护性
  • 降低变更代码带来的风险

里式替换原则LSP

里氏替换原则的最初定义是继承必须确保超类所拥有的性质在子类中仍然成立,听起来可能有些绕,但其实就是说子类对象可以替换父类对象,实现父类对象原有的所有方法。

从另一个角度出发,就是子类只能扩展父类的功能,而不能修改或删除父类原有的功能,具体实现就是:

  • 子类可以将父类的抽象方法进行实现,但不能删改父类原有的非抽象方法
  • 子类可以增加自己独有的方法
  • 子类在对父类方法进行重载时,参数列表必须包含父类方法的所有参数
  • 子类在对父类方法进行重载时,输出值格式必须比父类的输出格式更加严格

优点

  • 使得继承更加有序
  • 体现了开闭原则
  • 提高代码的可维护性

接口隔离原则ISP

接口隔离原则,要求程序员为各个功能不同的类建立专用的接口,而不是建立一个庞大的公共接口进行依赖。它有些类似单一职责原则,但更强调的是类和接口的关系。 为了实现接口隔离原则,我们应该遵循这些规则:

  • 类与类的依赖应该建立在一个尽可能小(功能专一)的接口上
  • 减少功能臃肿的接口
  • 尽量细化接口,一个接口的方法不能太多

优点

  • 高内聚、低耦合
  • 降低接口的复杂度
  • 提高代码的可读性和可维护性
  • 降低变更代码带来的风险

迪米特法则LoD

迪米特法则将类“拟人化”,类和类之间应该保持陌生的关系,一个类要尽可能的知晓其他类的相关信息,所以它又叫做最少知道原则。它的核心思想其实还是在降低类之间的耦合,提高模块之间的独立性。 实现迪米特法则,其实就是实现低耦合的过程:

  • 减少类之间的关联、聚合和组合关系
  • 尽量避免一个类对象可以直接访问其他类对象的方法
  • 迪米特法则将出现在一个类的成员变量、函数方法的输入输出中的类称作前者的朋友类

优点

  • 低耦合
  • 降低类的复杂度
  • 提高代码的可读性和可维护性

合成复用原则CARP

合成复用原则,要求在进行代码复用时,优先考虑组合或者聚合,而非继承关系。在使用继承关系时,同样需要严格遵循里式替换原则,二者都是开闭原则的具体实施规范。

优点

  • 规范了代码复用时的类间关系
  • 体现了开闭原则
  • 提高代码的可维护性