3.1 设计原则概述
六大设计原则分别如下:
1、单一职责原则(Single Responsibitity Principle)
2、开放封闭原则(Open Close Principle)
3、里氏替换原则(Liskov Substitution Principle)
4、接口分离原则(Interface Segregation Principle)
5、依赖倒置原则(Dependence Inversion Principle)
6、迪米特法则(Law Of Demter)
3.2 单一职责原则
3.2.1 定义
一个类或者模块只负责完成一个职责(或者功能)
3.2.2 解释
在类的设计中 我们不要设计大而全的类,而是要设计粒度小、功能单一的类.
如何判断一个类的职责是否单一?
没有一个具体的金科玉律,但从实际代码开发经验上,有一些可执行性的侧面判断指标,可供参考:
-
类中的代码行数、函数、或者属性过多;
-
类依赖的其他类过多
-
私有方法过多
-
类中大量的方法都是集中操作类中的几个属性
例子:
用户信息
同样的信息,也可分为用户信息、地址信息
3.3 开闭原则
3.3.1 定义
开闭原则规定软件中的对象、类、模块和函数对扩展应该是开放的,但对于修改是封闭的。这意味着应该用抽象定义结构,用具体实现扩展细节,以此确保软件系统开发和维护过程的可靠性。
3.3.2 解释
定义:对扩展开放,对修改关闭
优点:
-
新老逻辑解耦,需求发生改变不会影响老业务的逻辑
-
改动成本最小,只需要追加新逻辑,不需要改的老逻辑
-
提供代码的稳定性和可扩展性
例子:
顶层设计思维
- 抽象意识
- 封装意识
- 扩展意识
3.4 里氏替换原则
3.4.1 定义
如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致。
3.4.2 解释
替换的前提是面向对象语言所支持的多态特性,同一个行为具有多个不同表现形式或形态的能力。
在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。
例子:
在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。
Context 中代码使用接口定义对象变量,这个对象变量可以是实现了lStrategy接口的PromotionalStrategy、RebateStrategy 、 ReduceStrategy任意一个。
里氏代换原则与多态的区别 ?
多态是面向对象编程的一 大特性,也是面向对象编程语言的一种语法。它是一种代码实现的思路。
里式替换是一种 设计原则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类的时候,不 改变原有程序的逻辑及不破坏原有程序的正确性。
里氏替换原则和依赖倒置原则,构成了面向接口编程的基础,正因为里氏替换原则,才使得程序呈现多样性。
3.5 接口隔离原则
3.5.1 定义
一个类对另一个类的依赖应该建立在最小的接口上
3.5.2 解释
要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。
接口隔离原则与单一职责原则的区别
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者是不同的:
- 单一职责原则主要是约束类,它针对的是程序中的实现和细节。
- 接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。
例子:
微服务用户系统提供了一组跟用户相关的 API 给其他系统 使用,比如:注册、登录、获取用户信息等。
遵照接口隔离原则,为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
将删除接口单独放到另外 一个接口 RestrictedUserService 中, 然后将 RestrictedUserService 只打包提供给后台管理系统来 使用。
遵循接口隔离原则的优势
- 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
- 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
- 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码.
3.6 依赖倒置原则
3.6.1 定义
依赖倒置原则(Dependence Inversion Principle,DIP)是指在设计代码架构时,高层模块不应该依赖于底层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
3.6.2 解释
依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
传统的自定向下的设计
依赖倒置原则
例子:
根据依赖倒转原则进行改进:
关于依赖倒置、依赖注入、控制反转这三者之间的区别与联系
1 ) 依赖倒置原则
高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。
2 ) 控制反转
"控制"指的是对程序执行流程的控制,而"反转"指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员"反转"给了框架。
3 ) 依赖注入
我们不通过 new 的方式在类内部创建依赖的对象,而是将依赖的对象在外部创建好之后,通过构造函数等 方式传递(或注入)进来, 给类来使用。
3.7 迪米特法则
3.7.1 定义
迪米特法则(LoD:Law of Demeter)又叫最少知识原则(LKP:Least Knowledge Principle ),指的是一个类/模块对其他的类/模块有越少的了解越好。简言之:talk only to your immediate friends(只跟你最亲密的朋友交谈),不跟陌生人说话。
3.7.2 解释
不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。
例子:
3.8 设计原则总结
- 单一职责原则(SRP)
- 开闭原则(OCP)
- 里氏替换原则(LSP)
- 接口隔离原则(ISP)
- 依赖倒置原则(DIP)
- 迪米特法则 (LKP)
我们只需要重点关注三个常用的原则即可:
1 ) 单一职责原则
单一职责原则是类职责划分的重要参考依据,是保证代码"高内聚"的有效手段,是我们在进行面向对象设计时的主要指导原则。
2 ) 开闭原则
开闭原则是保证代码可扩展性的重要指导原则,是对代码扩展性的具体解读。很多设计模式诞生的初衷都是为了提高代码的扩展性,都是以满足开闭原则为设计目的的。
3 ) 依赖倒置原则
依赖倒置原则主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。