三、1如何运用设计原则之SOLID原则写出高质量代码?

news/2024/11/22 12:52:10/

你好我是程序员雪球。接下来我们学习一些经典的设计原则。其中包括SOLID,KISS,YAGNI,DRY,LOD等。其实这些设计原则从字面意思理解并不难。但是“看懂”和“会用”是两回事,而“用好”就难上加难了。

先来了解SOLID原则,他是由5个原则的首字母组成,分别是单一职责原则,开闭原则,里氏替换原则,接口隔离原则和依赖反转原则。

9384507cb62f467b9647c5a13b9d6984.png

 

单一职责原则(SRP)
指的是一个类或者一个模块只负责完成一个职责(或功能)。也就是说不要设计大而全的类,要设计粒度小,功能单一的类。单一职责原则是为了实现代码高内聚,低耦合,提高代码的复用性,可读性,可维护性。但是拆得过细,反倒会降低内聚性,影响可维护性 。

如何判断类的职责是否单一?
如果类的设计出现下面的情况,这可以判断不符合单一职责:
1、类中代码行数,函数和属性过多;
2、类依赖的其他类过多,或者依赖类的其他类过多;
3、私有方法过多;
4、比较难给类起一个命名;
5、类中的大量方法都是集中操作类中的某几个属性;

开闭原则(OCP)
开闭原则指的是软件实体(模块,类,方法等)应该“对扩展开发,对修改关闭”。也就是添加一个新的功能时,应该在已有的代码基础是扩展新的模块,类,方法等,而不是修改已有代码(模块,类,方法等),所以说代码的扩展性是重点。

提高代码的扩展性有哪些方法?
多态,依赖注入,基于接口而非实现编程,以及大部分的设计模式(装饰,策略,模板,职责链,状态等)。

如何在项目中灵活应用开闭原则?
对于比较确定,短期内可能会扩展,或者需求改动对代码影响较大的情况,或者实现成本不高的扩展点,在编码代码的时候,可以事先做些扩展设计。对未来不确定,或者实现起来比较复杂的扩展点,你可以等有需求驱动的时候,再通过代码重构的方式来支持扩展的需求。代码的扩展性有时会跟可读性相冲突,你需要做好权衡。

里氏替换原则(LSP)
指的是子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。其核心思想“按照约定来设计”,这里的约定包括:函数生命要实现的功能;对输入,输出,异常的约定;甚至包括注释中所罗列的任何特殊说明。

接口隔离原则(ISP)
指的是:客户端不应该被迫依赖它不需要的接口,其中的“客户端”可以理解为接口的调用者或者使用者。“接口”可以理解为下面三种场景:一组API接口集合,单个API接口或函数,OOP中的接口概念。接下来我们一起来解读这三种场景。

一组API接口集合
可以是某个微服务的接口,也可以说某个类库的接口。如果部分接口被部分调用者使用,你可以将这部分接口隔离出来,单独给这部分调用者使用。比如app前后端分离的接口实现中,我们应该将后台管理和APP前台的接口分开定义,应该像删除这里功能一般只有后台管理才有权限,这样可以做到隔离保护,避免前台用户误删用户信息。

单个API接口或函数
部分调用者只需要函数中的部分功能,那你可以将函数拆分成粒度更细的对个函数,让调用者只依赖它需要的那个细粒度函数。函数的设计功能要单一,不要将多个不同的功能逻辑在一个函数实现,这样可以提高代码的可读性和可维护性。

OOP的接口概念。
指的是面向对象编程语言的接口语法,接口设计要单一,不要让接口的实现类也调用者,依赖不需要的接口函数。比如JAVA中的interface,假如你在项目中用了三个外部系统:Redis,MySQL,Kafka。每个系统都对应一系列配置信息,比如地址,端口,访问超时等。为了在内存中存储这些配置信息,供项目中的其他模块来使用,我们分别设计实现了三个Configuretion类:RedisConfig,MysqlConfig,KafkaConfig。这样更加灵活,易扩展,易复用。

接口隔离原则和单一职责原则的区别
单一职责原则是针对模块,类和接口设计。接口隔离原则侧重于接口的设计,它是提供了一种判断接口的职责是否单的标准,即调用者只使用部分接口或者接口功能,那接口的设计就不够单一。

依赖反转原则(DIP)
我们先来了解三个概念:控制反转(IOC),依赖注入(DI),依赖注入框架(DIF)。

控制反转(IOC)
“控制”指的是程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用了框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员“反转”到了框架。控制反转是一种比较笼统的设计思想,一般用来指导框架层面的设计,比如模板设计模式,依赖注入方式等。

依赖注入(DI)
是一种编程技巧,不通过new()的方式在类内部创建依赖类对象,而是将依赖的类对象在外部创建好之后,通过构造函数,构造参数等方式传递(或注入)给类使用,这样提高了代码的扩展性。

依赖注入框架(DIF)
我们通过依赖注入框架提供的扩展点,简单配置所需要的类,以及类与类之间依赖关系,就可以实现由框架来自动创建对象,管理对象是生命周期,依赖注入等原本需要程序员来做的事情。

依赖反转原则(DIP)
高层模块不依赖底层模块,高层模块和底层模块应该通过抽象来相互依赖。除此之外,抽象不依赖具体的细节,具体实现细节依赖抽象。我们拿Tomcat这个Servlet容器为例子:
tomcat是运行java web应用程序的容器。那么tomcat是高层模块,web应用就是底层模块。tomcat与web应用代码直接没有直接的依赖关系,两者都依赖同一个“抽象”,也就是Servlet规范。servlet规格不依赖具体的tomcat容器和web应用的实现细节,而tomcat容器和web应用依赖servlet规范。

 


http://www.ppmy.cn/news/709339.html

相关文章

二、QT工程中各个文件代表的含义

QT从入门到实战学习笔记 基本QT工程中各个文件知识1、main函数2、.pro工程文件3、QT5基本模块4、.h头文件 基本QT工程中各个文件知识 1、main函数 #include "mymainwindow.h" #include <QApplication> //包含一个应用程序类的头文件 //main程序入口 argc命…

vue嵌入app中——首次加载慢的动画

背景&#xff1a;项目首次加载过慢&#xff0c;需要下载的资源比较大&#xff1b;白屏时间过长&#xff0c;导致用户体验不好&#xff1b; 解决办法&#xff1a;index.html 下载完&#xff0c;&#xff08;首页下载完&#xff09;就像执行动画 伸手党代码&#xff1a; 加粗样…

multiwii 2.4配置页面中文注释

1 #ifndef CONFIG_H_ 2 #define CONFIG_H_ 3 4 /* *********************************************************************************************** */ 5 /* *** 可配置参数 *** */ 6 /* ***************…

一个利用浏览器原生execCommand()方法实现的富文本编辑器

这是一个利用浏览器原生execCommand()方法实现的富文本编辑器&#xff0c;同时具有本地存储、定时保存、纯文本编辑器的功能&#xff0c;仅用于学习参考&#xff0c;其实并没有什么卵用。 新手上路&#xff0c;Bug太多&#xff0c;功能不完善&#xff0c;代码、变量太乱&…

PHP base64转图片

//转图片public function tupian(){$base64_image_content data:image/png;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAg…

multiwii 2.4配置中文注释

1 #ifndef CONFIG_H_2 #define CONFIG_H_3 4 /*************************************************************************************************/5 /**** 可配置参数 ****/6 /******************************…

GB50254-2014电气装置安装工程低压电器施工及验收规范

为保证低压电器的安装质量,促进施工安装技术进步&#xff0c;确保设备安装后的安全运行,制定本规范。 本规范适用于交流 50Hz或60Hz额定电压为 1000V 及以下&#xff0c;直流额定电压为 1500V 及以下通用低压电器的安装与验收。不适用于: 1、无需固定安装的家用电器、电工仪器…

JavaScript this和bind、apply、call

this指向函数执行时的当前对象&#xff0c;它会随着执行环境的改变而改变。this 是保留关键字&#xff0c;无法被修改任何函数本质上都是通过某个对象来调用的所有函数内部都有一个变量this&#xff0c;他的值是调用函数的当前对象 this指向 在事件中&#xff0c;this 表示接…