重构手法整理

news/2024/10/24 3:22:25/

提示:文章

文章目录

文章目录

      • 文章目录
  • 前言
  • 一、背景
  • 二、重构手法
    • 2.1 以委托取代继承
    • 2.2 使用c++实现
  • 三、
    • 3.1
  • 总结

前言

前期疑问:
本文目标:


一、背景

最近

二、重构手法

2.1 以委托取代继承

以委托取代继承是指我们常常为了一时的便利而错误地在代码中使用到了继承机制。我们知道,继承可以使得子类获得了父类的非私有方法、属性,而我们却正好是看中了这种无形中的便利而不正当地在逻辑上几乎不相关的类之间使用了继承,实质上这种为追求便利的继承是无意义的。

具体请看下面的代码。

// 重构前
class Sanitation {public String washHands() {return "Cleaned ...";}
}class Child extends Sanitation {}

在这里,卫生设备 Sanitation 类(假设为水龙头)具有给人们洗手的方法 washHands() ,但是这里的 Child 类想要具有 washHands() 的方法,但是完全不可以像上面那样子去 extends Sanitation 类啊,这两个类之间完全没有一点支持继承的联系。为了打破我们这种无意义的继承,以及消除这种带来不良影响的便利,我们应该进行重构,利用委托来实现。
重构第一步,先保留 extends 关系,这样便于一点点地检测我们的重构是否出错,如下:

class Sanitation {public String washHands() {return "Cleaned ...";}
}// 重构是一小步一小步进行的,先保留 extends 关系
class Child extends Sanitation{// 具有委托对象 Sanitation 的实例private Sanitation sanitation;public Child() {// 为委托对象赋值为当前对象,// 因为我们还保留了 extends 关系this.sanitation = this;}public String washHands() {// 这里使用委托获得  washHands() 方法 return (this.sanitation.washHands());}
}

当我们编译发现没有错误时(这时还不能运行,会发生栈溢出!),立即将上面 Child 类中的extends 去掉,并记得将构造函数中的 this 引用改成真正的创建一个 Sanitation 对象。
重构第二步:

class Child {// 具有委托对象 Sanitation 的实例private Sanitation sanitation;public Child() {// 删除 extends 关系this.sanitation = new Sanitation();}public String washHands() {// 这里使用委托获得  washHands() 方法 return (this.sanitation.washHands());}
}

至此,重构成功了!这才可以运行测试了。

小结:用委托取代这种“莫名其妙”的继承关系,是比较符合逻辑的。像 Child 和 Sanitation 两个类,根本就不是一个继承树上的,原先代码结构表现出来的也是毫无意义的。此外,个人认为,《重构》这本书上对于每个重构的步骤讲得比较详细,但是《31天重构》这本书的这一篇文章中的这个例子比《重构》中的似乎更合理些,因为这里的代码是用了一个逻辑上没有继承关系的例子,就想上文。

2.2 使用c++实现

尝试使用c++实现,下面进过自己调试后的代码

// Sanitation.h文件

#ifndef TESTPROJ_LOCAL_WITHOUT_LIBRARY_REFACTOR_H
#define TESTPROJ_LOCAL_WITHOUT_LIBRARY_REFACTOR_H#include <iostream>class Sanitation {
public:std::string washHands() {std::cout << "Cleaned ..." << std::endl;return "Cleaned ...";}
public:int sanitationCount;        // 这边假设子类不需要继承这些成员
};class Child : public Sanitation {};class ChildReflactor : public Sanitation{// 具有委托对象 Sanitation 的实例
private:Sanitation* sanitation;public:ChildReflactor() {// 为委托对象赋值为当前对象,// 因为我们还保留了 extends 关系this->sanitation = this;}public:std::string washHands() {// 这里使用委托获得  washHands() 方法return (this->sanitation->washHands());}
};#endif //TESTPROJ_LOCAL_WITHOUT_LIBRARY_REFACTOR_H

// Sanitation.cpp文件

#include "sanitation.h"int main()
{Child child;child.washHands();ChildReflactor childReflactor;childReflactor.washHands();
}

打印结果:

Cleaned ...
Cleaned ...

在上述代码中,如果按照实例写成this.sanitation = this; 会报错,改成指针就行。查了下c++的this是指针。

而且上述代码运行时没有出现栈溢出的情况,不知道是不是因为我的Sanitation成员是指针。

三、

3.1


总结

未完待续


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

相关文章

【VUE】v-show 和 v-if 的区别

v-show 始终会保留对应的 HTML 元素&#xff0c;只是在隐藏时通过 CSS 样式控制元素不可见&#xff1b;而 v-if 会根据表达式的值条件地渲染或销毁对应的 HTML 元素。v-show 是基于 CSS 的切换&#xff0c;切换速度相对较快&#xff0c;但对页面的渲染效率影响较大&#xff1b;…

MySQL中的最左前缀匹配原则

最左前缀匹配原则是 MySQL 在使用索引时遵循的一种规则&#xff0c;尤其在涉及到组合索引&#xff08;联合索引&#xff09;时。 最左前缀匹配原则指的是在使用组合索引时&#xff0c;MySQL 会从最左边的索引列开始匹配&#xff0c;直到遇到第一个无法继续匹配的列为止。这意味…

LeetCode 1750.删除字符串两端相同字符后的最短长度

题目&#xff1a; 给你一个只包含字符 a&#xff0c;b 和 c 的字符串 s &#xff0c;你可以执行下面这个操作&#xff08;5 个步骤&#xff09;任意次&#xff1a; 选择字符串 s 一个 非空 的前缀&#xff0c;这个前缀的所有字符都相同。选择字符串 s 一个 非空 的后缀&#…

linux,socket编程,select,poll,epoll学习

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> // 添加这一行 #include <string.h> // 添加这一行 #inc…

Java知识巩固(四)

目录 线程的生命周期 一、新建状态&#xff08;New&#xff09; 二、就绪状态&#xff08;Runnable&#xff09; 三、运行状态&#xff08;Running&#xff09; 四、阻塞状态&#xff08;Blocked&#xff09; 五、死亡状态&#xff08;Dead&#xff09; 什么是双亲委派 …

QGraphics类型学习使用【Qt】【C++】

QGraphics类型学习使用 需求过程全部完整代码 首先已知&#xff0c;QGraphicsView&#xff0c;QGraphicsScene, QGraphicsItem&#xff0c;分别称为&#xff1a;视图&#xff0c;场景&#xff0c;图元&#xff0c;图表就是各种各样的元素&#xff0c;图片元素&#xff0c;线条元…

【橙子老哥】C# 实操分布式事务解决方案

hello&#xff0c;大家好&#xff0c;今天来到橙子老哥的分享时间&#xff0c;希望大家一起学习&#xff0c;一起进步。 欢迎加入.net意社区&#xff0c;第一时间了解我们的动态&#xff0c;文章第一时间分享至社区 社区官方地址&#xff1a;https://ccnetcore.com (上千.net…

【Hive】8-Hive性能优化及Hive3新特性

Hive性能优化及Hive3新特性 Hive表设计优化 Hive查询基本原理 Hive的设计思想是通过元数据解析描述将HDFS上的文件映射成表 基本的查询原理是当用户通过HQL语句对Hive中的表进行复杂数据处理和计算时&#xff0c;默认将其转换为分布式计算 MapReduce程序对HDFS中的数据进行…