• 含义:
    以类代替原本单独存在的数值
  • 坏处:
    单独存在的数值不易于理解,也不符合面向对象的思想。
  • 目标:
    使数值尽量用类代替,就像java中的基本类型那样。
  • 实现方法:
    • 单独存在的数据值,考虑使用Replace Data Value with Object (以对象取代数据值)
    • 如果想要替换的数据值是类型码,而这些类型码并不影响行为,则可以运用Replace Type Code with Class (以类取代类型码)
    • 如果有与类型码相关的条件表达式,可运用Replace Type Code with Subclass (以子类替代类型码)Replace Type Code with State/Strategy(以状态/策略取代类型码)
    • 如果有一组总是放在一起的字段,可运用Extract Class(提取类)
    • 如果你在参数列中看到基本型数据,试试Introduce Parameter Object

本文涉及的重构方法

Introduce Parameter Object(引入参数对象)

Extract Class(提取类)

Replace Data Value with Object (以对象取代数据值)

  • 作用:
    消除那些与其他数据和方法在一起使用才有意义的数据项
  • 步骤:
  1. 为这个数值新建一个类,类型跟这个数值的类型一样,添上构造函数和get方法。
  2. 将原来类中的那个数值替换为前面新建的类,然后修改这个类里对原数值的调用为那个get函数。如果这个数值在原来的代码中还要支持修改,则在这个新类中添加set函数。修改原来类中的设值部分为新类的set函数。
  3. 编译,测试
  4. 这个新类如果产生了过多实例,想合成为一个,考虑使用Change Value to Reference(将值对象改为引用)
  • 代码实例
//假设有个代表用户的类User, 里面有个数值叫address,我希望改用一个对象来表示地址,以后就更好扩展
//原代码如下:
class User {private String address;public User(String address) {this.address = address;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}
}
//现在我们把address这个数值搬出来作为一个类
//修改后代码如下
class User {private Address address;public User(String address) {this.address = new Address(address);}public String getAddress() {return address.getDetail();}public void setAddress(String address) {this.address = new Address(address);}
}class Address {private String detail;public Address(String detail) {this.detail = detail;}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}
}
  • 重构思路:
    把函数中那些数值尽量用类去替代之。类中写好构造函数,set/get方法,然后把原代码中对这个数值的操作部分改为这个类。重构完后,继续使用Change Value to Reference(将值对象改为引用) 继续优化代码。

Change Value to Reference(将值对象改为引用)

  • 作用:
    从类中创建了过多的实例,而这些实例实际上可以用同一个对象代替
  • 步骤:
  1. 使用Replace Constructor with Factory Method (使用工厂函数替代构造器)
  2. 编译,测试
  3. 考虑这个类由什么对象提供访问新对象的途径(比如:静态字典或者注册表对象,也可以用多个对象作为访问点)
  4. 考虑这个对象中引用的对象哪些是需要提前创建好的,哪些需要动态创建的。
  5. 修改工厂函数,使它返回引用对象
  6. 编译,测试
  • 代码实例
//以上文中列举的例子为基础进行改进
//首先把Address类的构造方法改为工厂
class Address {private String detail;//声明构造函数为私有private Address(String detail) {this.detail = detail;}//建立工厂函数public static Address create (String detail) {return new Address(detail);}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}
}
//改变原来User类引用的地方改为调工厂函数
class User {private Address address;public User(String address) {this.address = Address.create(address);}public String getAddress() {return address.getDetail();}public void setAddress(String address) {this.address = new Address(address);}
}
//如果引用的地方的对象需要预先创建好,方便调用,可以修改程序为以下
class Address {//建立静态变量储存需要预先实例化的对象private static HashMap<Address> instances = new HashMap<Address>();private String detail;//声明构造函数为私有private Address(String detail) {this.detail = detail;}static void preloadAddresses () {new Address("北京路").store();new Address("南京路").store();new Address("东京路").store();new Address("西京路").store();}private void store() {instances.put(this.getDetail(), this);}//建立工厂函数//优化代码,返回已经创建好的实例//由于实际上此方法已经不是create的意思,修改方法名为getNamedpublic static Address getNamed (String detail) {return instances.get(detail);}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}
}
  • 重构思路:
    可以结合上一个案例来看,前一个案例中,每次实例化都会new 一个 address,在setAddress时也会new,造成大量实例,这些实例,实际上可以用同一个代替,采用工厂方法,并预先实例化大量需要用的实例就能解决此问题。

Replace Type Code with Class (以类取代类型码)

  • 重构思路:
    此方法现在已经过时,思想是以类代替代码中的各类类型码,实际上现在可以使用枚举类实现此重构手法。故不作赘述。

Replace Type Code with Subclass (以子类替代类型码)

  • 作用:
    消除代码中的不可变的那些类型码
  • 步骤:
  1. 把这个类型码变量使用 Self Encapsulate Field(自封装字段) 封装起来, 如果该类型码传给了构造函数,需要将构造函数换成工厂函数。
  2. 根据类型码对应的变量建立相应的子类,对子类里获取类型码的变量的函数进行覆写。
  3. 把父类中保存类型码字段删除,将类型码的获取函数声明为抽象函数。
  4. 编译,测试
  • 代码实例
//根据水果类型码构建不同的水果,创建水果对象时根据type确定水果类型
class Fruit {private int type;static final int APPLE = 0;static final int PEAR = 1;static final int BANANA = 2;Fruit(int type) {this.type = type;}
}
//重构后
class Fruit {static final int APPLE = 0;static final int PEAR = 1;static final int BANANA = 2;abstract int getType();static Fruit create(int type) {switch (type) {case APPLE : return new Apple();case PEAR : return new Pear();case BANANA : return new Banana();default: throw new IllegalArgumentException("参数不正确!");}}
}class Apple extends Fruit {int getType() {return Fruit.APPLE;}
}
//其他水果类略...
  • 重构思路:
    我个人觉得意义不大,本重构法同样可以用枚举代替,枚举类内写上通过类型码获取对应实例就好。本身这样的写法也只是徒增了类的数量,实际代码的整洁度感觉不太明显,有点牵强地强行套用面向对象的思想。

Replace Type Code with State/Strategy(以状态/策略取代类型码)

  • 重构思路:
    参考状态模式和策略模式,以增加类数量的代价实现代码的简洁。

Replace Array with Object (以对象取代数组)

  • 代码实例
//重构前
String[] row = new String[3];
row[0] = "语文";
row[1] = "K-14";
//重构后
Classroom cr = new Classroom();
cr.setName("语文");
cr.setNum("K-14");
  • 重构思路:
    以对象取代数组,把数组中的元素改为对象中的属性。

简单易懂读《重构》 - Primitive Obesession (基本类型偏执)相关推荐

  1. 简单易懂读《重构》 - Speculative Generality (高估未来的可能性)

    含义: 高估未来的扩展性,添加过多不必要的类,方法或继承体系 坏处: 不利于程序维护,可读性差 目标: 依现实来重新评估,去除多余的代码部分. 实现方法: 使用Collapse Hierarchy ( ...

  2. 简单易懂读《重构》 - Feature Envy (依恋情结)

    含义: 某个函数为了实现其功能,经常从另一个类中获取大量数据.比起自身所在的类来说,更加依赖于另一个类 坏处: 代码结构混乱,类分功不明确,可能造成其他坏味道. 目标: 确定类的具体作用,并合理摆置每 ...

  3. 简单易懂读《重构》 - Inappropriate Intimacy(不合适的亲昵关系)

    不合适的亲昵关系 含义: 两个类间互相依赖,总是调用对方的过多属性. 坏处: 代码耦合度高,破坏类的独立性 目标: 把联系过分紧密部分搬移或者建立新类放在其中. 实现方法: 使用Move Method ...

  4. 公式太多,读不懂? 一文带你领略KNN近邻算法~简单易懂

    ↑ 点击上方[计算机视觉联盟]关注我们 K近邻算法采用测量不同特征值之间的距离方法进行分类. K-近邻算法工作原理: 存在一个样本数据集合,也称作训练样本集,并且样本集中的每个数据都存在标签,即我们知 ...

  5. 【转】区块链是什么,如何简单易懂地介绍区块链?

    作者:知乎用户 链接:https://www.zhihu.com/question/37290469 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 友情提醒:比特币 ...

  6. ISO7816协议深度解析-简单易懂协议详解(一)-- 复位,字符帧,及ATR

    1. 摘要 IC卡必须支持T=0或T=1的协议,但不是同时支持这两种协议,而终端则必须同时支持T=0和T=1的协议. • T=0通讯协议是异步半双工字符传输协议: • T=1通讯协议是异步半双工块传输 ...

  7. JavaScript面向对象--继承 (超简单易懂,小白专属)...

    JavaScript面向对象--继承 (超简单易懂,小白专属) 一.继承的概念 子类共享父类的数据和方法的行为,就叫继承. 二.E55如何实现继承?探索JavaScript继承的本质 2.1构造函数之 ...

  8. C语言:简易商品库存管理系统(简单易懂,不用指针的入门级示例,数据结构大作业)

    C语言:商品库存管理系统(简单易懂,不用指针的入门级示例) 没有使用指针,没有写入文件,全部是最基础的c语言语句,本程序使用vc6.0测试 功能: 1.创建商品的信息 2.显示全部商品对信息(商品数量 ...

  9. eltable 无数据文案修改_写文案不断打磨修改,让你的文案简单易懂

    我们在写文案的时候,创意可能就在某一个瞬间产生,但是我们想写出让自己满意的文案,所需要花的时间可能远远多于创意产生所花的时间,海明威说过,"写作就是修改",写文案也是如此,需要不断 ...

最新文章

  1. oracle12c安装卡住_windows上安装oracle 12c到69%时卡住不动解决方案
  2. 双活数据中心技术架构(PDF版)
  3. linux type命令(用来显示指定命令的类型,判断给出的指令是内部指令还是外部指令,如果给出的指令为外部指令,则显示其绝对路径)
  4. Subversion的权限控制
  5. .Net Core应用框架Util介绍(三)
  6. HTML5本地图片裁剪并上传
  7. LeetCode 764. 最大加号标志(DP)
  8. 虚拟机与服务器桥接不能上网,vmware虚拟机桥接模式不能上网
  9. oracle9.2.04下载,Linux AS3.0下安装ORACLE9.2.04
  10. 第五章 站在巨人的肩膀上
  11. 微型计算机是啥课,微机课是什么意思
  12. win10小娜不能使用解决方案
  13. css3实现3d图片旋转效果
  14. 关于程序员成长的一点思考
  15. k8s——flannel网络
  16. 靶机渗透练习84-The Planets:Earth
  17. java万年历的设计总结_java万年历设计报告
  18. QM的计算机专业,PCM5-QM170
  19. 搁浅争议共同开发_搁浅!
  20. 盈通rx580游戏高手 bios_RX 5700 XT D6 游戏高手测评:女装大佬重捶出击!

热门文章

  1. oracle部分命令
  2. 复制源码大师宋利兵谈MySQL 8.0的复制改进,大赞
  3. 阿里云、腾讯云、百度云、京东云、华为云、盛大云、ucloud他们之间优势分别是?
  4. USACO hamming
  5. Java IO(BIO)
  6. Redis 错误Please check the Redis logs for details about the RDB error解决
  7. 用python实现维吉尼亚密码的加密与唯密文解密
  8. 分布式温度采集模块在玻璃制造中的应用
  9. 【我所認知的BIOS】--第一条指令
  10. 懒人有懒福,推荐个朗读软件