Skip to content

Commit

Permalink
add: liskov principle
Browse files Browse the repository at this point in the history
  • Loading branch information
hscspring committed Oct 23, 2022
1 parent b1a90de commit ce1ac80
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ https://datawhalechina.github.io/sweetalk-design-pattern/#/
| | 开闭原则 | 长琴 |
| | 依赖倒置原则 | 胡锐锋 |
| | 迪米特原则 | 碧涵 |
| | 里氏替换原则 | 长琴 |
| 设计模式 | 简单工厂模式、策略模式、装饰模式、代理模式、工厂方法模式 | 肖桐 |
| | 原型模式、模板方法模式、外观模式、建造者模式 | 碧涵 |
| | 观察者模式、抽象工厂模式、状态模式、适配器模式 | 长琴 |
Expand Down Expand Up @@ -85,6 +86,7 @@ README.md------------------------------------------项目说明

### ChangeLog

- v1.2完成初版 221023
- v1.1完成笔记 221008
- v1.0基础结构 220916

Expand Down
4 changes: 2 additions & 2 deletions docs/content/design_principles/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# 设计原则

本部分介绍设计原则,书中一共提到四个原则
本部分介绍设计原则,书中一共提到以下几个原则

- 单一职责原则(Single Responsibility Principle,SRP):修改一个类的原因只有一个。
- 开闭原则(Open-Closed Principle,OCP):对于扩展类应该开放,对于修改类应该封闭。
- 迪米特法则(Law of Demeter,LoD):也叫最少知识原则,类应尽量降低成员的访问权限,即耦合尽可能弱。
- 依赖倒置原则(Dependency Inversion Principle,DIP):高层次的类不应依赖低层次的类,都应依赖于抽象接口。
- 里氏替换原则(Liskov Substituion Principle,LSP):扩展一个类时,能够(不修改代码)将子类的对象作为父类对象进行传递。和依赖倒置原则意思接近。

此外,还有下面常见的设计原则:

- 里氏替换原则(Liskov Substituion Principle,LSP):扩展一个类时,能够(不修改代码)将子类的对象作为父类对象进行传递。和依赖倒置原则意思接近。
- 接口隔离原则(Interface Segregation Principle,ISP):尽量缩小接口范围,让客户端不必实现不用的方法。和迪米特法则接近。
- 合成/聚合复用原则(Composite/Aggragate Reuse Principle,CARP):尽量通过合成/聚合而不是继承达到复用目的。

Expand Down
29 changes: 22 additions & 7 deletions docs/content/design_principles/dependence_inversion_principle.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
# 依赖倒置原则

## 1 概念
依赖倒置原则,Dependence Inversion Principle,简称 DIP,是指程序不应该依赖细节,细节应该依赖于抽象。简单来说,就是要针对接口编程,不要针对实现编程。

  依赖倒置原则(Dependence Inversion Principle, DIP)是程序不应该依赖细节,细节应该依赖于抽象。简单来说,就是要针对接口编程,不要针对实现编程。
**使用动机**

## 2 知识点
面对不同的具体实现做到易拔插,松耦合。

- 高层模块不应该依赖低层模块,两个都应该依赖抽象
- 抽象不应该依赖细节,细节应该依赖抽象
- 依赖倒置的中心思想是面向接口编程
- 使用接口或抽象类的目的是制定好规范,不涉及任何具体的操作,把展现细节的任务交给实现类去完成
**如何使用**

- 使用接口或抽象类的目的是制定好规范,不涉及任何具体的操作,把展现细节的任务交给实现类去完成。
- 让程序中的所有依赖关系都终止于抽象类或接口。

**使用原则**

- 高层模块不应该依赖低层模块,两个都应该依赖抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。

**使用示例**

以计算机为例。

刚开始的计算机是自成体系的,虽然都是采用同样的设计架构和结构,但组件之间的连接方式不同。如果用 A 公司的电脑,硬盘坏了后只能用 A 公司提供的硬盘。这是一种紧耦合的表现,每个组件将其内部实现暴露给外部对接。

后来几家大公司统一了标准,约定好组件之间连接的标准,标准后面具体怎么做,由相应公司自己负责。这样的结果是,我们既可以使用 A 公司的硬盘,也可以使用 B 公司的硬盘。不光如此,不同大小(如 500G 和 200G)、不同结构(如固态硬盘和机械硬盘)的硬盘也可以互换。真正实现了可拔插、易拔插。

除了硬盘,其他如 CPU、内存、外设设备等各种设备组件也都实现了标准化接口。所有的对接都发生在接口层面,不需要关心具体的实现细节。
29 changes: 29 additions & 0 deletions docs/content/design_principles/liskov_substituion_principle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 里氏替换原则

里氏替换原则,Liskov Substituion Principle,简称 LSP,一个软件实体如果使用的是一个父类的话,一定适用于其子类,而且它察觉不出父类和子类的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化。简单来说,子类型必须能够替换掉它们的父类型。

**使用动机**

父类能够真正复用(继承),子类也能够在父类的基础上增加新的行为。

**如何使用**

- 父类一般使用抽象类或接口。
- 抽象类定义公共对象和状态;接口定义公共行为。
- 子类通过继承父类和接口进行扩展。

**使用原则**

- 子类方法的参数类型必须与父类相匹配或更抽象。
- 子类的返回值类型必须与父类或其子类相匹配。
- 子类方法的异常必须与父类能抛出的异常(或其子类)相匹配。
- 子类不应该加强参数条件限制。
- 子类不能修改父类的私有成员变量。

**使用示例**

以企鹅和鸟为例。

假设鸟是父类,有下蛋和飞翔两个方法。企鹅作为鸟如果继承了父类,就会出现问题,因为企鹅虽然有翅膀但不会飞。所以,这样设计父类和子类是不合理的,它违反了上面提到的原则,企鹅作为子类无法替换父类。

合理的做法是将飞翔的行为抽象为接口,父类鸟描述状态和公共方法(比如吃),然后会飞的子类再去实现飞翔接口,不会飞的就不用管了。

0 comments on commit ce1ac80

Please sign in to comment.