第3部分 设计原则
如果建筑的架构设计不佳,那么其所用的砖头质量再好也没有用。这就是SOLID设计原则所要解决的问题。
SOLID原则的主要作用就是告诉我们如何将数据和函数组织成为类,以及如何将这些类链接起来成为程序。
我们为软件构建中层结构的主要目标如下:
- 使软件可容忍被改动。
- 使软件更容易被理解。
- 构建可在多个软件系统中复用的组件。
SOLID原则应该直接紧贴于具体的代码逻辑之上,这些原则是用来帮助我们定义软件架构中的组件和模块的。
SRP:单一职责原则
一个软件系统的最佳结构高度依赖于开发这个系统的组织的内部结构。这样,每个软件模块都有且只有一个需要被改变的理由。
OCP:开闭原则
如果软件系统想要更容易被改变,那么其设计就必须允许新增代码来修改系统行为,而非只能靠修改原来的代码。
LSP:里氏替换原则
如果想用可替换的组件来构建软件系统,那么这些组件就必须遵守同一个约定,以便让这些组件可以相互替换。
ISP:接口隔离原则
这项设计原则主要告诫软件设计师应该在设计中避免不必要的依赖。
DIP:依赖反转原则
高层策略性的代码不应该依赖实现底层细节的代码,恰恰相反,那些实现底层细节的代码应该依赖高层策略性的代码。
第7章 SRP:单一职责原则
任何一个软件模块都应该有且仅有一个被修改的原因。
任何一个软件模块都应该只对某一类行为者负责。
多人为了不同的目的修改了同一份源代码,这很容易造成问题的产生。而避免这种问题产生的方法就是将服务不同行为者的代码进行切分。
第8章 OCP:开闭原则
设计良好的计算机软件应该易于扩展,同时抗拒修改。
如果A组件不想被B组件上发生的修改所影响,那么就应该让B组件依赖于A组件。
软件系统不应该依赖其不直接使用的组件
OCP是我们进行系统架构设计的主导原则,其主要目标是让系统易于扩展,同时限制其每次被修改所影响的范围。实现方式是通过将系统划分为一系列组件,并且将这些组件间的依赖关系按层次结构进行组织,使得高阶组件不会因低阶组件被修改而受到影响。
第9章 LSP:里氏替换原则
果对于每个类型是S的对象o1都存在一个类型为T的对象o2,能使操作T类型的程序P在用o2替换o1时行为保持不变,我们就可以将S称为T的子类型。
LSP可以且应该被应用于软件架构层面,因为一旦违背了可替换性,该系统架构就不得不为此增添大量复杂的应对机制。
第10章 ISP:接口隔离原则
任何层次的软件设计如果依赖了它并不需要的东西,就会带来意料之外的麻烦。
第11章 DIP:依赖反转原则
如果想要设计一个灵活的系统,在源代码层次的依赖关系中就应该多引用抽象类型,而非具体实现。
在应用DIP时,我们也不必考虑稳定的操作系统或者平台设施,因为这些系统接口很少会有变动。我们主要应该关注的是软件系统内部那些会经常变动的(volatile)具体实现模块,这些模块是不停开发的,也就会经常出现变更。
稳定的抽象层
- 应在代码中多使用抽象接口,尽量避免使用那些多变的具体实现类。
- 不要在具体实现类上创建衍生类。
- 不要覆盖(override)包含具体实现的函数。在这里,控制依赖关系的唯一办法,就是创建一个抽象函数,然后再为该函数提供多种具体实现。
- 应避免在代码中写入与任何具体实现相关的名字,或者是其他容易变动的事物的名字。
工厂模式
利用抽象工厂模式来管理依赖关系
源代码依赖方向永远是控制流方向的反转——这就是DIP被称为依赖反转原则的原因。
任意一个软件都能反映出其制作团队的组织结构,这是因为人们会以反映他们组织形式的方式工作。换句话说,分散的团队可能用分散的架构生成系统。项目团队的组织结构中的优点和弱点都将不可避免地反映在他们生成的结果系统中