重构——写在后面

2023-11-04

重构方法有很多,但是只要满足以下条件,怎么重构都是合理的:

原则一:(SRP:Single responsibility principle)单一职责原则又称单一功能原则

核心:解耦和增强内聚性(高内聚,低耦合)

描述:

类被修改的几率很大,因此应该专注于单一的功能。如果你把多个功能放在同一个类中,功能之间就形成了关联,

改变其中一个功能,有可能中止另一个功能,这时就需要新一轮的测试来避免可能出现的问题。

原则二:开闭原则(OCP:Open Closed Principle)

核心思想:对扩展开放,对修改关闭。即在设计一个模块的时候,应当使这个模

块可以在不被修改的前提下被扩展。

根据开闭原则,在设计一个软件系统模块(类,方法)的时候,应该可以在不修改原有的模块(修改关闭)的基础上,能扩展其功能(扩展开放)。

扩展开放:

某模块的功能是可扩展的,则该模块是扩展开放的。软件系统的功能上的可扩展性要求模块是扩展开放的。

修改关闭:

某模块被其他模块调用,如果该模块的源代码不允许修改,则该模块修改关闭的。软件系统的功能上的稳定性,持续性要求是修改关的。

原则三:里氏替换原则(LSP:Liskov Substitution Principle)

核心:

1.在任何父类出现的地方都可以用他的子类来替代(子类应当可以替换父类并出现在父类能够出现的任何地方)

子类必须完全实现父类的方法。在类中调用其他类是务必要使用父类或接

口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。

2.子类可以有自己的个性。子类当然可以有自己的行为和外观了,也就是方

法和属性

3.覆盖或实现父类的方法时输入参数可以被放大。即子类可以重载父类的方法,但输入参数应比父类方法中的大,这样在子类代替父类的时候,调用的仍然是父类的方法。即以子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松。

4.覆盖或实现父类的方法时输出结果可以被缩小。

原则四:依赖倒转原则(DIP:Dependence Inversion Principle)

别名:依赖倒置原则或依赖反转原则

核心:要依赖于抽象,不要依赖于具体的实现

1.高层模块不应该依赖低层模块,两者都应该依赖其抽象(抽象类或接口)

2.抽象不应该依赖细节(具体实现)

3.细节(具体实现)应该依赖抽象。

三种实现方式:

1.通过构造函数传递依赖对象

2.通过setter方法传递依赖对象

3.接口声明实现依赖对象

原则五:接口分离原则(ISP:Interface Segregation Principle)

核心思想:

不应该强迫客户程序依赖他们不需要使用的方法。

接口分离原则的意思就是:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口当中.

分离接口的两种实现方法:

1.使用委托分离接口。(Separation through Delegation)

2.使用多重继承分离接口。(Separation through Multiple Inheritance)

原则六:合成复用原则(CRP:Composite Reuse Principle)

核心思想:

尽量使用对象组合,而不是继承来达到复用的目的。该原则就是在一个新的对象里面使用一些已有的对象,

使之成为新对象的一部分:新的对象通过向这些对象的委派达到复用已有功能的目的。

复用的种类:

1.继承

2.合成聚合

注:在复用时应优先考虑使用合成聚合而不是继承

原则七:迪米特原则(LOD:Law of Demeter)

又叫最少知识原则

核心思想:

一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。

(类间解耦,低耦合)意思就是降低各个对象之间的耦合,提高系统的可维护性;在模块之间只通过接口来通信,

而不理会模块的内部工作原理,可以使各个模块的耦合成都降到最低,促进软件的复用

注:

1.在类的划分上,应该创建有弱耦合的类;

2.在类的结构设计上,每一个类都应当尽量降低成员的访问权限;

3.在类的设计上,只要有可能,一个类应当设计成不变;

4.在对其他类的引用上,一个对象对其它对象的引用应当降到最低;

5.尽量降低类的访问权限;

6.谨慎使用序列化功能;

7.不要暴露类成员,而应该提供相应的访问器(属性)

UML统一建模语言,java中七种设计原则

UML统一建模语言。

类与类,类和接口,接口和接口之间的关系。

1、实现关系(一个类实现一个接口)

2、泛化关系(一个类继承另一个类)

3、关联(1)、依赖关系:一个类是另一个类的方法局部变量,方法的参数或方法返回值。2)、聚合关系:一个类是另一个类的属性,是整体和部分的关系。3)、组合关系:一个类是另一个类的属性,是整体不可分割的一部分,是强聚合。)

4、单一职责:一个类而言,应该仅有一个引起它变化的原因,永远不要让一个类存在多个改变的理。一个类只应该做和一个任务相关的业务,不应该把过多的业务放在一个类中完成。

迪米特法则:

一个软件实体应当尽可能少的与其他实体发生相互作用。

七种设计原则总结

单一职责原则:一个类只应该做和一个职责相关的事情,不要把过多的业务放在一个类中完成。

迪米特法则:软件实体之间应该做到最少的交互。不要和陌生人说话。调用方只关心他需要使用的方法

接口隔离原则:使用专门的接口,比用统一的接口要好。便于分工,在实现接口时,不应该看到自己不用关心的方法。

开闭原则:软件实体应该对扩展开放,对修改关闭。开闭原则是设计原则的核心原则,其他的设计原则都是开闭原则表现和补充。实现开闭原则的方法就是抽象。

聚合/组合复用原则。多使用聚合/组合达到代码的重用,少使用继承复用。

依赖倒置原则:面向抽象编程,不要面向具体编程。

面向对象七大设计原则

1、 开闭原则

2、 里氏替换原则

3、 单一职责原则

4、 接口隔离原则

5、 依赖倒置原则

6、 迪米特原则

7、组合/聚合复用原则

知识点关联

学习面向对象的设计模式,是深入面向对象思想的钥匙,通过大师级的微妙案例,我们可以开阔自己的认知。

在学习面向对象设计七大原则之前,我们要对基本的封装、继承、多态思想有足够的了解,对抽象类和接口也要有足够的编码能力,因为设计模式是以上知识点的综合应用。

另外,在接触具体的设计模式之前,面向对象的七大设计原则会让你知道,设计模式出现的必然性和意义所在。

1、 每一种设计思想的精准含义,具体如下:

先从整体认识这七种设计思想。

一、开闭原则:

这一条放在第一位来理解,它的含义是对扩展开放,对修改关闭。解释一下就是,我们写完的代码,不能因为需求变化就修改。我们可以通过新增代码的方式来解决变化的需求。

当然,这是一种理想的状态,在现实中,我们要尽量的缩小这种修改。

再解释一下这条原则的意义所在,我们采用逆向思维方式来想。如果每次需求变动都去修改原有的代码,那原有的代码就存在被修改错误的风险,当然这其中存在有意和无意的修改,都会导致原有正常运行的功能失效的风险,这样很有可能会展开可怕的蝴蝶效应,使维护工作剧增。

说到底,开闭原则除了表面上的可扩展性强以外,在企业中更看重的是维护成本。

所以,开闭原则是设计模式的第一大原则,它的潜台词是:控制需求变动风险,缩小维护成本。

以下几种原则,都是为此原则服务的。

二、里氏替换选择:

此原则的含义是子类可以在任何地方替换它的父类。解释一下,这是多态的前提,我们后面很多所谓的灵活,都是不改变声明类型的情况下,改变实例化类来完成的需求变更。当然,继承的特性看似天然就满足这个条件。但这里更注重的是继承的应用问题,我们必须保证我们的子类和父类划分是精准的。

里氏替换原则的潜台词是:尽量使用精准的抽象类或者接口。

三、单一职责原则:

单一职责的含义是:类的职责单一,引起类变化的原因单一。解释一下,这也是灵活的前提,如果我们把类拆分成最小的职能单位,那组合与复用就简单的多了,如果一个类做的事情太多,在组合的时候,必然会产生不必要的方法出现,这实际上是一种污染。

举个例子,我们在绘制图案的时候,用“点”组成图和用“直线”组成图,哪个更灵活呢?一定是“点”,它可以绘制任何图形,而直线只能绘制带有直线条的图案,它起码无法画圆。

单一职责的潜台词是:拆分到最小单位,解决复用和组合问题。

四、接口隔离原则:

接口隔离原则可以说是单一职责的必要手段,它的含义是尽量使用职能单一的接口,而不使用职能复杂、全面的接口。很好理解,接口是为了让子类实现的,如果子类想达到职能单一,那么接口也必须满足职能单一。

相反,如果接口融合了多个不相关的方法,那它的子类就被迫要实现所有方法,尽管有些方法是根本用不到的。这就是接口污染。

接口隔离原则的潜台词是:拆分,从接口开始。

五、依赖倒置原则:

想要理解依赖倒置原则,必须先理解传统的解决方案。面相对象的初期的程序,被调用者依赖于调用者。也就是调用者决定被调用者有什么方法,有什么样的实现方式,这种结构在需求变更的时候,会付出很大的代价,甚至推翻重写。

依赖倒置原则就是要求调用者和被调用者都依赖抽象,这样两者没有直接的关联和接触,在变动的时候,一方的变动不会影响另一方的变动。

其实,依赖倒置和前面的原则是相辅相成的,都强调了抽象的重要性。

依赖倒置的潜台词是:面向抽象编程,解耦调用和被调用者。

六、迪米特原则:

迪米特原则要求尽量的封装,尽量的独立,尽量的使用低级别的访问修饰符。这是封装特性的典型体现。

一个类如果暴露太多私用的方法和字段,会让调用者很茫然。并且会给类造成不必要的判断代码。所以,我们使用尽量低的访问修饰符,让外界不知道我们的内部。这也是面向对象的基本思路。这是迪米特原则的一个特性,无法了解类更多的私有信息。

另外,迪米特原则要求类之间的直接联系尽量的少,两个类的访问,通过第三个中介类来实现。

迪米特原则的潜台词是:不和陌生人说话,有事去中介。

七、组合/聚合复用原则:

此原则的含义是,如果只是达到代码复用的目的,尽量使用组合与聚合,而不是继承。这里需要解释一下,组合聚合只是引用其他的类的方法,而不会受引用的类的继承而改变血统。

继承的耦合性更大,比如一个父类后来添加实现一个接口或者去掉一个接口,那子类可能会遭到毁灭性的编译错误,但如果只是组合聚合,只是引用类的方法,就不会有这种巨大的风险,同时也实现了复用。

组合聚合复用原则的潜台词是:我只是用你的方法,我们不一定是同类。

2、 在学习面向对象七大设计原则时需要注意以下几点:

a) 高内聚、低耦合和单一职能的“冲突”

实际上,这两者是一回事。内聚,要求一个类把所有相关的方法放在一起,初看是职能多,但有个“高”,就是要求把联系非常紧密的功能放在一起,也就是说,从整体看,是一个职能的才能放在一起,所以,两者是不同的表述而已。

这里很多人理解成复合类,但复合类不是高内聚,而是杂乱的放在一起,是一种设计失误而已。

b) 多个单一职能接口的灵活性和声明类型问题

如果一个类实现多个接口,那么这个类应该用哪个接口类型声明呢?应该是用一个抽象类来继承多个接口,而实现类来继承这个接口。声明的时候,类型是抽象类。

c) 最少知识原则和中介类泛滥两种极端情况

这是另一种设计的失误。迪米特原则要求类之间要用中介来通讯,但类多了以后,会造成中介类泛滥的情况,这种情况,我们可以考虑中介模式,用一个总的中介类来实现。

当然,设计模式都有自己的缺陷,迪米特原则也不是十全十美,交互类非常繁多的情况下,要适当的牺牲设计原则。

d) 继承和组合聚合复用原则的“冲突”

继承也能实现复用,那这个原则是不是要抛弃继承了?不是的。

继承更注重的是“血统”,也就是什么类型的。而组合聚合更注重的是借用“技能”。并且,组合聚合中,两个类是部分与整体的关系,组合聚合可以由多个类的技能组成。在C#和Java中只有单继承。

这个原则不是告诉我们不用继承了,都用组合聚合,而是在“复用”这个点上,我们优先使用组合聚合。

面向对象设计原则的共性问题:

1、这么多设计模式,都要学习和使用么?

答:我们只是掌握总体的原则,然后学习常用的就行了。实际开发中也不是每种设计模式都会经常用到。因为归根结底,设计模式也好,架构也好,都是为需求服务的,没有需求业务模型,不能生搬硬套模式。我们在学习的时候,多学一些总是好的,但只是为了开阔自己的眼界。

2、设计模式是规范么?是不是好的程序必须用设计模式?

答:严格来说,好的程序遵循的是设计原则,而非设计模式。现在就出现很多新的演变出来的模式,这些都是因为出现了新业务的原因,设计模式不是规范,只是一种借鉴。

3、使用设计模式会不会增加开发难度?

答:开发阶段会的,而且会延长开发时间。但一个项目或产品从开始到结束,开发只是其中很小的一部分,考虑到维护和扩展成本,才会出现设计模式。从整体考虑,设计模式是减少了开发时间和成本的。

关于七种面向对象设计原则

面向对象设计原则是我们用于评价一个设计模式的使用效果的重要标准之一。

下面我给大家介绍一下七种设计原则各是什么,以及其定义:

单一职责原则 定义:一个类只负责一个领域的相应职责

开闭原则 定义:软件实体应对扩展开放,而对修改关闭

里氏替换原则 定义:所有引用基类的对象能够透明的使用其子类的对象

依赖倒转原则 定义:抽象不应该依赖于细节,细节依赖于抽象

接口隔离原则 定义:使用多个专门的接口,而不是使用单一总接口

合成复用原则 定义:尽量使用对象组合,而不是继承来达到复合目的

迪米特法则 定义:一个软件实体应当尽可能少的与其它实体发生相互作用

其中比较常用的是红色字体,蓝色字体仅次,黑色字体基本不使用。

里氏替换原则:父类出现的方法,子类一定可以替换。如果子类不能完整实现父类方法,或者父类的方法在子类中已经发生了畸变,那么就要断开父子关系。采用依赖、聚合、组合等关系替代继承。里氏替换原则可以用于检测两个类是否具有父子关系。

7种常用的面向对象设计原则

设计原则名称

定义

使用频率

单一职责原则

(Single Responsibility Principle, SRP)

一个类只负责一个功能领域中的相应职责

★★★★☆

开闭原则

(Open-Closed Principle, OCP)

软件实体应对扩展开放,而对修改关闭

★★★★★

里氏代换原则

(Liskov Substitution Principle, LSP)

所有引用基类对象的地方能够透明地使用其子类的对象

★★★★★

依赖倒转原则

(Dependence Inversion Principle, DIP)

抽象不应该依赖于细节,细节应该依赖于抽象

★★★★★

接口隔离原则

(Interface Segregation Principle, ISP)

使用多个专门的接口,而不使用单一的总接口

★★☆☆☆

合成复用原则

(Composite Reuse Principle, CRP)

尽量使用对象组合,而不是继承来达到复用的目的

★★★★☆

迪米特法则

(Law of Demeter, LoD)

一个软件实体应当尽可能少地与其他实体发生相互作用

★★★☆☆

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重构——写在后面 的相关文章

  • 文件I/O和标准I/O的区别

    文件I O 文件I O是操作系统提供的操作文件的API 例如Linux中的open 和write 等 这些函数可以完成文件的操作 但是效率不一定很高 标准I O 标准I O是应用层提供的库函数 例如C语言提供的文件操作函数fopen fcl
  • Qt信息隐藏(Q_D/Q_Q)介绍

    目录 1 基本介绍与二进制兼容 2 二进制兼容的设计原则 3 常见c qt信息隐藏 4 Q Q Q D介绍 5 定制可编辑treewidget与如何访问基类的Private 6 总结 1 基本介绍与二进制兼容 作者虽然一直在linux做开发
  • Vue + Spring Boot 项目实战(分享)

    第一部分Vue Spring Boot 项目实战 一 项目简介Vue Spring Boot 项目实战 二 搭建 Vue js 项目Vue Spring Boot 项目实战 三 前后端结合测试 登录页面开发 Vue Spring Boot
  • Google earth engine学习笔记 2: 通过分析提取植被物候的代码学习gee 1

    Google earth engine学习笔记 2 通过分析提取植被物候的代码学习gee 1 通过一篇 根据 sentinel 2 影像计算植被指数并提取植被物候 的文章所附的代码学习gee 原作者的github 写这个东西是为了自己学习
  • python-scrapy框架(三)Pipeline文件的用法讲解

    Pipeline是一个独立的模块 用于处理从Spider中提取的Item对象 实现对数据的进一步处理 存储和清洗等操作 下面将详细介绍Scrapy框架中Pipeline的用法 1 创建Pipeline类 为了使用Pipeline类 我们需要

随机推荐

  • 物联网终端算法

    物联网终端算法是指在物联网终端设备上运行的各种算法 包括数据采集 数据预处理 数据传输 数据存储 数据处理 数据分析等算法 以下是物联网终端算法的一些具体应用 数据采集算法 用于采集各种传感器数据 包括温度 湿度 气压 光照 声音 震动等信
  • 华为OD机试 Java 实现【最优策略组合下的总的系统消耗资源数】【牛客练习题】,附详细解题思路

    目录 一 题目描述 二 输入描述 三 输出描述 四 解题思路 五 Java算法源码 六 效果展示 1 输入 2 输出 3 说明 4 思路 华为OD机试 2023B卷题库疯狂收录中 刷题点这里 一 题目描述 在通信系统中有一个常见的问题是对用
  • 0成本的售卖高考资料虚拟资源,这样的玩法顶得上一家大公司

    在这个快速发展 每天的信息成千上万的世界中 对于网络从业者来说 网络的信息就是金钱 以至于让活在当下的大多数年轻人 中年人 甚至在校学生 都会想在互联网这个金矿去分一块肉吃 但是每个人的时间都是平等的 一天24小时出去吃饭睡觉 甚至除去上班
  • 同时校验手机号和座机号

    文章目录 同时校验手机号和座机号 一 使用实例 同时校验手机号和座机号 filter方法是js中常用的方法 提示 以下是本篇文章正文内容 下面案例可供参考 一 使用实例 1 同时校验手机号和座机号 export function check
  • 机器学习-XGBoost

    一 XGBoost是什么 XGBoost是基于GBDT实现的 但GBDT算法只利用了一阶的导数信息 xgboost对损失函数做了二阶的泰勒展开 并在目标函数之外加入了正则项对整体求最优解 用以权衡目标函数的下降和模型的复杂程度 避免过拟合
  • 手机java开发环境,看完跪了

    01 分布式限流 Nginx ZooKeeper 1 1 分布式限流之Nginx 请解释一下什么是 Nginx 请列举 x Nginx 的一些特性 请列举 x Nginx 和 和 Apache 之间的不同点 请解释 x Nginx 如何处理
  • VUE实用技术点

    1 路由懒加载 能让你首次加载更快 路由懒加载可以让我们的包不需要一次把所有的页面的加载进来 只加载当前页面的路由组件就行 举个栗子 如果这样写 加载的时候会全部都加载进来 const router new VueRouter routes
  • ESDA in PySal (2) localjoincounts

    ESDA in PySal 2 localjoincounts 参考 https blog csdn net angel0929 article details 128433265 https blog csdn net allenlu20
  • 知乎转来的、、、Nuitka用法

    Python打包exe的王炸 Nuitka Python与模具 Python在制造领域的使用 关注 1 726 人 赞同了该文章
  • Ubuntu安装JDK1.8(手动解压JDK压缩包)

    1 官网下载JDK https www oracle com technetwork java javase downloads jdk8 downloads 2133151 html 2 解压缩 下载的版本jdk 8u211 linux
  • ubuntu18.04安装wireshark3.x与tshark3.x

    默认安装tshark会是2 x 以下是安装3 x的方法 使用命令 sudo add apt repository ppa wireshark dev stable sudo apt update 安装wireshark3 x sudo ap
  • IPv6 PMTUD 路径发现机制 工作原理

    Technorati 标签 IPv6 PMTUD PMTUD IPv6 PMTUD是IPv6的一个工作机制 其主要的目的就是 当网络源发送数据报文到目的的时候 避免分段 也可以称为分片 源节点可以使用发现整个路径上面最大的MTU与目的节点通
  • Android opengles2.0 背景透明

    在Android上开发OpenGL ES应用时 默认的背景不透明的 即使使用了glClearColor来设置了不透明度为0 且纹理图片中有透明的部分也可能被GLView的背景填充 那么首先解决GLView的透明背景问题吧 要设置透明的第一步
  • python-gitlab

    一 安装 pip install python gitlab 官方文档 http python gitlab readthedocs io en stable API https docs gitlab com ce api project
  • springboot项目层次结构_SpringBoot 项目目录结构(工程结构)

    一 代码层结构 根目录 com jianbao 启动类JianbaoApplication java推荐放在根目录 com jianbao 包下 数据实体类domain jpa项目 com jianbao domain mybatis项目
  • 江西理工大学计算机网络基础试卷,无线网络技术作业(江西理工大学期末复习)...

    无线网络技术 1 1 跳频扩频和直接序列扩频各有什么特点 我的答案 跳频扩频 1 一定扩频码序列进行选择的多频率频移键控调制 载波频率不断跳变 2 发送方看似随机的无线电频率序列广播消息 并以固定间隔从一频率跳到另一频率 3 接收方接收时也
  • java对象和类的定义 属性 方法

    类 class 对象 Object instance 实例 1 类可以看成一类对象的模板 对象可以看成该类的一个具体实例 2 类是用于描述同一类型的对象的一个抽象概念 类中定义了这一类对象所应具有的共同属性 方法 类的定义方式 每一个源文件
  • JSP数据交互(一)---内置对象》response

    JSP内置对象之response response对象用于响应客户请求并向客户端输出信息 设置响应参数等 页面重定向 void sendRedirect String location 客户端将重新发送请求到指定的URL 实现登陆验证 并验
  • vector、list、queue

    引用 windows程序员面试指南 vector vector 类似于C语言中的数组 vector 支持随机访问 访问某个元素的时间复杂度 O 1 vector 插入和删除元素效率较低 时间复杂度O n vector 是连续存储 没有内存碎
  • 重构——写在后面

    重构方法有很多 但是只要满足以下条件 怎么重构都是合理的 原则一 SRP Single responsibility principle 单一职责原则又称单一功能原则 核心 解耦和增强内聚性 高内聚 低耦合 描述 类被修改的几率很大 因此应