[关闭]
@Alpacadh 2022-09-18T17:23:11.000000Z 字数 3266 阅读 259

Part.2 设计原则

设计模式


1、单一职责原则(SRP)

主要思想:一个类或者模块只负责完成一个职责(或者功能)

1.1 如何判断职责是否单一

1.2 如何设计

1.3 什么时候需要代码拆分

2、开闭原则(OCP)

主要思想:软件实体(模块、类、方法等)应该“对扩展开放、对修改关闭”,即在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。

2.1 如何做到开闭原则

2.2 如何在日常开发中灵活应用开闭原则

3、里氏替换原则(LSP)

主要思想:子类对象可以替换程序中父类对象。

3.1 哪些代码逻辑违背了里式替换原则

4、接口隔离原则(ISP)

主要思想:客户端不应该被强迫依赖它不需要的接口。其中的“客户端”,可以理解为接口的调用者或者使用者。

4.1 如何理解“接口隔离原则”?

理解“接口隔离原则”的重点是理解其中的“接口”二字。这里有三种不同的理解。

5、依赖反转原则(DIP)

主要思想:这条原则跟控制反转有点类似,主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。

5.1 如何理解依赖反转原则

点击展开内容

6、KISS原则

主要思想:代码尽量简单。

6.1 如何写出满足KISS原则的代码

7、DRY原则

主要思想:不要写重复的代码。重复主要指实现逻辑重复、功能语义重复和代码执行重复。

8、代码复用性

8.1 如何提高代码复用性

9、迪米特法则(LOD)

主要思想:不该有直接依赖关系的类之间,不要有依赖;有依赖关系的类之间,尽量只依赖必要的接口。

10、代码分层的意义

1.分层能起到代码复用的作用

同一个Repository可能会被多个Service来调用,同一个Service可能会被多个Controller调用。比如,UserService中的getUserById()接口封装了通过ID获取用户信息的逻辑,这部分逻辑可能会被UserController和AdminController等多个Controller使用。如果没有Service层,每个Controller都要重复实现这部分逻辑,显然会违反DRY原则。

2.分层能起到隔离变化的作用

分层体现了一种抽象和封装的设计思想。比如,Repository层封装了对数据库访问的操作,提供了抽象的数据访问接口。基于接口而非实现编程的设计思想,Service层使用Repository层提供的接口,并不关心其底层依赖的是哪种具体的数据库。当我们需要替换数据库的时候,比如从MySQL到Oracle,从Oracle到Redis,只需要改动Repository层的代码,Service层的代码完全不需要修改。

除此之外,Controller、Service、Repository三层代码的稳定程度不同、引起变化的原因不同,所以分成三层来组织代码,能有效地隔离变化。比如,Repository层基于数据库表,而数据库表改动的可能性很小,所以Repository层的代码最稳定,而Controller层提供适配给外部使用的接口,代码经常会变动。分层之后,Controller层中代码的频繁改动并不会影响到稳定的Repository层。

3.分层能起到隔离关注点的作用

Repository层只关注数据的读写。Service层只关注业务逻辑,不关注数据的来源。Controller层只关注与外界打交道,数据校验、封装、格式转换,并不关心业务逻辑。三层之间的关注点不同,分层之后,职责分明,更加符合单一职责原则,代码的内聚性更好。

4.分层能提高代码的可测试性

后面讲单元测试的时候,我们会讲到,单元测试不依赖不可控的外部组件,比如数据库。分层之后,Repsitory层的代码通过依赖注入的方式供Service层使用,当要测试包含核心业务逻辑的Service层代码的时候,我们可以用mock的数据源替代真实的数据库,注入到Service层代码中。代码的可测试性和单元测试我们后面会讲到,这里你稍微了解即可。

5.分层能应对系统的复杂性

所有的代码都放到一个类中,那这个类的代码就会因为需求的迭代而无限膨胀。我们知道,当一个类或一个函数的代码过多之后,可读性、可维护性就会变差。那我们就要想办法拆分。拆分有垂直和水平两个方向。水平方向基于业务来做拆分,就是模块化;垂直方向基于流程来做拆分,就是这里说的分层。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注