当前位置: 首页 > article >正文

重构手法整理

提示:文章

文章目录

文章目录

      • 文章目录
  • 前言
  • 一、背景
  • 二、重构手法
    • 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.kler.cn/news/362242.html

相关文章:

  • SQL 自学:游标(Cursors)的理解与应用
  • R语言建模线性回归
  • PYQT5 简单项目实践
  • 【报错处理】MR/Spark 使用 BulkLoad 方式传输到 HBase 发生报错: NullPointerException
  • 算法题总结(十九)——图论
  • uniapp结合uview-ui创建项目
  • 【编程语言】C++ 中 vector 初始化的多种方法详解
  • Git_命令
  • Golang 并发编程:Context 包的使用与并发控制
  • MongoDB安装配置及配置和启动服务
  • 使用Docker启动的Redis容器使用的配置文件路径等问题以及Python使用clickhouse_driver操作clickhouse数据库
  • 微知-RDMA中的四大M,以及Mellanox驱动中的MAD为什么叫MA的D?(managent agent、Management Datagrams)
  • 与ai一起作诗(《校园清廉韵》)
  • MATLAB和Python电车电池制造性能度量分析
  • Selenium自动化测试工具
  • Pytorch复习(三)
  • VMware虚拟机软件安装、卸载
  • 免费开源Odoo软件如何实现电商仓库高效发货
  • 【WebGIS】Cesium:GLTF数据加载
  • <Project-11 Calculator> 计算器 0.2 工时计算器 WorkHours Calculator HTTP + JS
  • scrapy案例——豆瓣电影Top250的爬取
  • 高校危化试剂仓储系统|基于SprinBoot+vue的高校危化试剂仓储系统设计与实现(源码+数据库+文档)
  • 上拉电阻和下拉电阻在电路中的作用(一)
  • HTTP安全么?如何更好的保护您的网站
  • 软件程序系统架构中MVC和三层架构分别是什么,有什么区别?
  • Jmeter接口测试企业级项目实战day2