设计模式系列-第二章(设计原则-SOLID)_设计模式第二章完整代码-程序员宅基地

技术标签: 设计模式  

前言:SOLID 原则并非单纯的 1 个原则,而是由 5 个设计原则组成的,它们分别是:单一职责原则、开闭原则、里式替换原则、接口隔离原则和依赖反转原则,依次对应 SOLID 中的 S、O、L、I、D 这 5 个英文字母。

一、单一职责原则(SRP)

       单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。一个类或者模块只负责完成一个职责(或者功能)。单一职责原则是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、低耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。

判断是否单一职责

  • 类中的代码行数、函数或属性过多,会影响代码的可读性和可维护性,我们就需要考虑对类进行拆分;
  • 类依赖的其他类过多,或者依赖类的其他类过多,不符合高内聚、低耦合的设计思想,我们就需要考虑对类进行拆分;
  • 私有方法过多,我们就要考虑能否将私有方法独立到新的类中,设置为 public 方法,供更多的类使用,从而提高代码的复用性;
  • 比较难给类起一个合适名字,很难用一个业务名词概括,或者只能用一些笼统的 Manager、Context 之类的词语来命名,这就说明类的职责定义得可能不够清晰;
  • 类中大量的方法都是集中操作类中的某几个属性,比如,在 UserInfo 例子中,如果一半的方法都是在操作 address 信息,那就可以考虑将这几个属性和对应的方法拆分出来。

二、开闭原则(OCP)    

       开闭原则的英文全称是 Open Closed Principle,简写为 OCP。详细表述一下,那就是,添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)即对扩展开放、对修改关闭。

       添加一个新功能,不可能任何模块、类、方法的代码都不“修改”,这个是做不到的。类需要创建、组装、并且做一些初始化操作,才能构建成可运行的的程序,这部分代码的修改是在所难免的。我们要做的是尽量让修改操作更集中、更少、更上层,尽量让最核心、最复杂的那部分逻辑代码满足开闭原则。回到这条原则的设计初衷:只要它没有破坏原有的代码的正常运行,没有破坏原有的单元测试,我们就可以说,这是一个合格的代码改动。

       很多设计原则、设计思想、设计模式,都是以提高代码的扩展性为最终目的的。特别是 23 种经典设计模式,大部分都是为了解决代码的扩展性问题而总结出来的,都是以开闭原则为指导原则的。最常用来提高代码扩展性的方法有:多态、依赖注入、基于接口而非实现编程,以及大部分的设计模式(比如,装饰、策略、模板、职责链、状态)。

       基于一定的粒度(例如模块,类,属性等),扩展是平行地增加,修改是变更更细粒度的子集。扩展和修改和具体的粒度有关。不同的粒度下,扩展和修改定义不同。我个人以为,扩展的结果是引入了更多的平行结构(例如相似的派生类handler),以及支持这些平行结构的代码(利用多态,在关键的地方使用接口)。这些引入会让代码结构变的扁平一些,但是也更晦涩一些。修改,往往会增加代码的深度(这里指更低粒度的复杂度),例如,文中log例子,修改后,check函数有五个参数,内部的if else逻辑更多。但是,如果从参数以及if作用域的角度,这也可算作扩展。所以,扩展还是修改更本质的区别在于修改发生的粒度和层次。通常偏好修改发生在更高的层次上,这要求我们能够用接口和组合把系统合理的切分,做到高内聚和低耦合。高内聚可以让修改发生在更高层次上,替换掉整个低层次实现细节。低耦合,可以让模块之间的调用最小化,可以让高层次的修改最小化。支持高层次的平行结构不是免费的,除非有明确的收益(例如文中隔离Kafka实现细节的例子),不然还是让重构等待到需要的那一刻,预测未来的大部分平行结构其实不会被真正用到。

三、里式替换原则(LSP)

        里式替换原则的英文翻译是:Liskov Substitution Principle,缩写为 LSP。

        里式替换原则是用来指导,继承关系中子类该如何设计的一个原则。理解里式替换原则,最核心的就是理解“design by contract,按照协议来设计”这几个字。父类定义了函数的“约定”(或者叫协议),那子类可以改变函数的内部实现逻辑,但不能改变函数原有的“约定”。这里的约定包括:函数声明要实现的功能;对输入、输出、异常的约定;甚至包括注释中所罗列的任何特殊说明。理解这个原则,我们还要弄明白里式替换原则跟多态的区别。虽然从定义描述和代码实现上来看,多态和里式替换有点类似,但它们关注的角度是不一样的。多态是面向对象编程的一大特性,也是面向对象编程语言的一种语法。它是一种代码实现的思路。而里式替换是一种设计原则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类的时候,不改变原有程序的逻辑及不破坏原有程序的正确性。

四、接口隔离原则(ISP)

        接口隔离原则的英文翻译是“ Interface Segregation Principle”,缩写为 ISP。直译成中文的话就是:客户端不应该被强迫依赖它不需要的接口。其中的“客户端”,可以理解为接口的调用者或者使用者。

        如果把“接口”理解为一组接口集合,可以是某个微服务的接口,也可以是某个类库的接口等。如果部分接口只被部分调用者使用,我们就需要将这部分接口隔离出来,单独给这部分调用者使用,而不强迫其他调用者也依赖这部分不会被用到的接口。如果把“接口”理解为单个 API 接口或函数,部分调用者只需要函数中的部分功能,那我们就需要把函数拆分成粒度更细的多个函数,让调用者只依赖它需要的那个细粒度函数。

接口隔离原则与单一职责原则的区别

       单一职责原则针对的是模块、类、接口的设计。接口隔离原则相对于单一职责原则,一方面更侧重于接口的设计,另一方面它的思考角度也是不同的。接口隔离原则提供了一种判断接口的职责是否单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。

五、依赖反转原则(DIP)

       依赖反转原则。依赖反转原则的英文翻译是 Dependency Inversion Principle,缩写为 DIP。依赖反转原则也叫作依赖倒置原则。这条原则跟控制反转有点类似,主要用来指导框架层面的设计。高层模块不依赖低层模块,它们共同依赖同一个抽象。抽象不要依赖具体实现细节,具体实现细节依赖抽象。

举例就是tomcat和Web 应用程序代码。Tomcat 和应用程序代码之间并没有直接的依赖关系,两者都依赖同一个“抽象”,也就是 Servlet 规范。Servlet 规范不依赖具体的 Tomcat 容器和应用程序的实现细节,而 Tomcat 容器和应用程序依赖 Servlet 规范。

控制反转(IOC)

控制反转的英文翻译是 Inversion Of Control,缩写为 IOC。

控制反转是一个比较笼统的设计思想,并不是一种具体的实现方法,一般用来指导框架层面的设计。这里所说的“控制”指的是对程序执行流程的控制,而“反转”指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程通过框架来控制。流程的控制权从程序员“反转”给了框架。
控制反转是一种编程思想,把控制权交给第三方。依赖注入是实现控制反转最典型的方法。

依赖注入(DI)

依赖注入是一种具体的编码技巧。我们不通过 new 的方式在类内部创建依赖类的对象,而是将依赖的类对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类来使用。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/king13127/article/details/115326631

智能推荐

2020CVPR-面向人脸反欺骗的单边域泛化_single-side domain generalization for face anti-sp-程序员宅基地

文章浏览阅读2.9k次。2020CVPR,Single-Side Domain Generalization for Face Anti-Spoofing,中科院,有源代码文章链接:Single-Side Domain Generalization for Face Anti-Spoofing (thecvf.com)https://openaccess.thecvf.com/content_CVPR_2020/papers/Jia_Single-Side_Domain_Generalization_for_Face_Anti_single-side domain generalization for face anti-spoofing

联想台式机BIOS升级教程(2018.8)_联想电脑bios升级教程-程序员宅基地

文章浏览阅读492次,点赞10次,收藏10次。BIOS(Basic Input/Output System)是计算机硬件与操作系统之间的桥梁,它负责在开机时初始化硬件设备,并为操作系统提供必要的信息。随着技术的发展,BIOS也需要不断升级以适应新的硬件和操作系统。对于联想台式机用户,BIOS升级可能会遇到一些困难。本文将分享联想台式机BIOS升级教程(2018.8),帮助大家轻松掌握BIOS升级的方法和步骤,确保计算机的正常运行和性能提升。无论您是初学者还是有一定经验的用户,相信本文都将为您提供有益的参考和指导。_联想电脑bios升级教程

python快速编程入门课本中的名片管理器_python优雅操作-实现名片管理系统-程序员宅基地

文章浏览阅读152次。python的确是适合零基础的编程爱好者学习的语言,python的程序能看懂,但是很难去实现,这是每一个学习python的新手们基本上都会遇到的难题。好记性不如烂笔头,把知识运用到实战项目中,这是最好的记忆法。在比较熟悉python常用的数据类型之后,我们可以开始优雅地操作一个小项目,实现名片管理系统能实现如下功能:名片管理系统1.添加名片2.删除名片3.修改名片4.查询名片5.退出系统0.显示所..._用编程实现名片管理器功能:

springboot+java技术+Mysql 数据库小说在线阅读系统 计算机毕业设计源码82630_spring boot读取数据库中的内容实现小说阅读-程序员宅基地

文章浏览阅读1.6k次,点赞7次,收藏11次。本文以java为开发技术,实现了一个小说在线阅读系统。小说在线阅读系统的主要使用者分为管理员、读者用户、作者用户;实现功能:首页、网站管理(轮播图、网站公告)人员管理(管理员、读者用户、作者用户)购物管理(小说商城、分类列表、订单列表)模块管理(小说类型、本周强推、点击榜单、更新榜单、创作作品、系统收入汇总、读者建议、作者建议、提现信息、稿费明细、稿费信息)个人管理等功能。通过这些功能模块的设计,基本上实现了整个小说信息管理的过程。具体在系统设计上,采用了B/S的结构,同时,也使用java技术在动态页面上_spring boot读取数据库中的内容实现小说阅读

2021CTF工业信息安全技能大赛-隐藏的工艺_ctf pcz-程序员宅基地

文章浏览阅读2.1k次。2021CTF工业信息安全技能大赛-隐藏的工艺工控安全工程师把工艺流程分享在论坛中,并留下关键敏感信息,你能找到相关线索吗?flag格式为:flag{}。二、解题步骤1.使用strings过滤查看图片发现隐藏在其中的PCZ文件,猜测为图片隐写;2.修改图片为zip可以解压需要密码3、需要密码尝试进行爆破得到FC00,解压获得一个01的文件夹4、使用7z查看其中是否隐藏有其它内容,在其中bmp下发现flag二维码图片。..._ctf pcz

斗鱼弹幕服务器第三方接入协议v1.6.2,.NET斗鱼直播弹幕客户端(上)-程序员宅基地

文章浏览阅读1k次。前言现在直播平台由于弹幕的存在,主播与观众可以更轻松地进行互动,非常受年轻群众的欢迎。斗鱼TV就是一款非常流行的直播平台,弹幕更是非常火爆。看到有不少主播接入 弹幕语音播报器、 弹幕点歌等模块,这都需要首先连接斗鱼弹幕。经常看到其它编程语言的开发者,分享了他们斗鱼弹幕客户端的代码。.NET当然也能做,还能做得更好(只是不知为何很少见人分享????)。本文将包含以下内容:我将使用斗鱼TV官方公开的弹幕PD..._斗鱼弹幕服务器

随便推点

shell 创建文件夹-程序员宅基地

文章浏览阅读1.6w次。#!/bin/bashdir="/root/test_dir"if [ ! -d "$dir" ];thenmkdir $direcho "创建文件夹成功"elseecho "文件夹已经存在"fi_shell 创建文件夹

SystemC的语言结构简介_system c-程序员宅基地

文章浏览阅读9.3k次,点赞7次,收藏35次。SystemC是解决系统级设计挑战的设计工具。在1999年的11月,世界最主要的EDA工具开发商、IP供应商、半导体厂家、系统和嵌入式软件公司宣布推出了Open SystemC Initiative(OSCI),同时提供了一个C++建模平台、即SystemC。SystemC是由一组C++类库所组成的建模平台,加入了一个仿真核,可以在系统级、行为描述级和寄存器转换级支持硬件建模。C/C++编程语_system c

基于Apache2.2配置虚拟域名访问_apache不配置域名能跑吗-程序员宅基地

文章浏览阅读5.3k次,点赞2次,收藏7次。最近在项目测试中用到了虚拟域名,因为是和sqlserver的数据库一块使用,所以使用的PHP版本和apache版本都比较低,自己配置了一遍后,做个笔记,希望对其他人也有帮助。1.进入到apache的文件目录下,打开httpd.conf文件2.打开文件后,搜索,rewrite,找到下面图片中的这一行,然后把#号去掉。继续搜索vhosts这一行,继续把注释#去掉3._apache不配置域名能跑吗

关于堆栈区别的总结_栈的大小是固定的吗-程序员宅基地

文章浏览阅读1.3k次。堆栈的区别管理方式不同:栈:栈区空间由操作系统分配与释放,用于存储局部变量、函数参数等。堆:堆区空间由程序员自主分配与释放。空间大小不同:栈:栈的大小是固定的,不同的操作系统也不同。window一般为2M,linux下为10M堆:理论上可以分配虚拟地址空间大小的内存。分配效率不同:栈分配空间的效率更高。栈的擦偶哦在硬件层提供支持。分配专门的寄存器来存储栈的地址,压栈出..._栈的大小是固定的吗

智源论坛报名丨斯坦福大学马腾宇博士:为深度模型设计显示正则器-程序员宅基地

文章浏览阅读182次。深度模型有高超的学习(数据拟合)能力,但为了提高模型的泛化能力、让模型在新的数据上也有好的表现,我们需要寻找一些方法干扰模型的训练过程,避免模型“记住”训练数据,这就是正则化。本次报告邀..._魏哲巍清华交叉信息研究院

服务器已联网 不能远程桌面,几种常见的Windows 服务器无法联网/无法连接远程桌面等故障解决方案...-程序员宅基地

文章浏览阅读8.5k次。SEO优化扫我一、服务器无法连接远程桌面1、Ping不通IP,网站打不开,不可以远程连接。可能是服务器死机了,或者网络有问题,请尝试Web重启服务器或联系服务商确认。2、Ping正常,网站可以打开,远程桌面无法连接,请尝试Web重启服务器或者联系服务商确认。另外你是否修改了远程桌面端口,而没有在防火墙例外该端口.3、终端服务器超出了最大允许连接数,Windows 2003 系统默认可以同时登陆2个..._windows 开启了远程桌面服务还是无法远程

推荐文章

热门文章

相关标签