简单易懂读《重构》 - Primitive Obesession (基本类型偏执)
- 含义:
以类代替原本单独存在的数值 - 坏处:
单独存在的数值不易于理解,也不符合面向对象的思想。 - 目标:
使数值尽量用类代替,就像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 (以对象取代数据值)
- 作用:
消除那些与其他数据和方法在一起使用才有意义的数据项 - 步骤:
- 为这个数值新建一个类,类型跟这个数值的类型一样,添上构造函数和get方法。
- 将原来类中的那个数值替换为前面新建的类,然后修改这个类里对原数值的调用为那个get函数。如果这个数值在原来的代码中还要支持修改,则在这个新类中添加set函数。修改原来类中的设值部分为新类的set函数。
- 编译,测试
- 这个新类如果产生了过多实例,想合成为一个,考虑使用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(将值对象改为引用)
- 作用:
从类中创建了过多的实例,而这些实例实际上可以用同一个对象代替 - 步骤:
- 使用Replace Constructor with Factory Method (使用工厂函数替代构造器)
- 编译,测试
- 考虑这个类由什么对象提供访问新对象的途径(比如:静态字典或者注册表对象,也可以用多个对象作为访问点)
- 考虑这个对象中引用的对象哪些是需要提前创建好的,哪些需要动态创建的。
- 修改工厂函数,使它返回引用对象
- 编译,测试
- 代码实例
//以上文中列举的例子为基础进行改进
//首先把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 (以子类替代类型码)
- 作用:
消除代码中的不可变的那些类型码 - 步骤:
- 把这个类型码变量使用 Self Encapsulate Field(自封装字段) 封装起来, 如果该类型码传给了构造函数,需要将构造函数换成工厂函数。
- 根据类型码对应的变量建立相应的子类,对子类里获取类型码的变量的函数进行覆写。
- 把父类中保存类型码字段删除,将类型码的获取函数声明为抽象函数。
- 编译,测试
- 代码实例
//根据水果类型码构建不同的水果,创建水果对象时根据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 (基本类型偏执)相关推荐
- 简单易懂读《重构》 - Speculative Generality (高估未来的可能性)
含义: 高估未来的扩展性,添加过多不必要的类,方法或继承体系 坏处: 不利于程序维护,可读性差 目标: 依现实来重新评估,去除多余的代码部分. 实现方法: 使用Collapse Hierarchy ( ...
- 简单易懂读《重构》 - Feature Envy (依恋情结)
含义: 某个函数为了实现其功能,经常从另一个类中获取大量数据.比起自身所在的类来说,更加依赖于另一个类 坏处: 代码结构混乱,类分功不明确,可能造成其他坏味道. 目标: 确定类的具体作用,并合理摆置每 ...
- 简单易懂读《重构》 - Inappropriate Intimacy(不合适的亲昵关系)
不合适的亲昵关系 含义: 两个类间互相依赖,总是调用对方的过多属性. 坏处: 代码耦合度高,破坏类的独立性 目标: 把联系过分紧密部分搬移或者建立新类放在其中. 实现方法: 使用Move Method ...
- 公式太多,读不懂? 一文带你领略KNN近邻算法~简单易懂
↑ 点击上方[计算机视觉联盟]关注我们 K近邻算法采用测量不同特征值之间的距离方法进行分类. K-近邻算法工作原理: 存在一个样本数据集合,也称作训练样本集,并且样本集中的每个数据都存在标签,即我们知 ...
- 【转】区块链是什么,如何简单易懂地介绍区块链?
作者:知乎用户 链接:https://www.zhihu.com/question/37290469 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 友情提醒:比特币 ...
- ISO7816协议深度解析-简单易懂协议详解(一)-- 复位,字符帧,及ATR
1. 摘要 IC卡必须支持T=0或T=1的协议,但不是同时支持这两种协议,而终端则必须同时支持T=0和T=1的协议. • T=0通讯协议是异步半双工字符传输协议: • T=1通讯协议是异步半双工块传输 ...
- JavaScript面向对象--继承 (超简单易懂,小白专属)...
JavaScript面向对象--继承 (超简单易懂,小白专属) 一.继承的概念 子类共享父类的数据和方法的行为,就叫继承. 二.E55如何实现继承?探索JavaScript继承的本质 2.1构造函数之 ...
- C语言:简易商品库存管理系统(简单易懂,不用指针的入门级示例,数据结构大作业)
C语言:商品库存管理系统(简单易懂,不用指针的入门级示例) 没有使用指针,没有写入文件,全部是最基础的c语言语句,本程序使用vc6.0测试 功能: 1.创建商品的信息 2.显示全部商品对信息(商品数量 ...
- eltable 无数据文案修改_写文案不断打磨修改,让你的文案简单易懂
我们在写文案的时候,创意可能就在某一个瞬间产生,但是我们想写出让自己满意的文案,所需要花的时间可能远远多于创意产生所花的时间,海明威说过,"写作就是修改",写文案也是如此,需要不断 ...
最新文章
- oracle12c安装卡住_windows上安装oracle 12c到69%时卡住不动解决方案
- 双活数据中心技术架构(PDF版)
- linux type命令(用来显示指定命令的类型,判断给出的指令是内部指令还是外部指令,如果给出的指令为外部指令,则显示其绝对路径)
- Subversion的权限控制
- .Net Core应用框架Util介绍(三)
- HTML5本地图片裁剪并上传
- LeetCode 764. 最大加号标志(DP)
- 虚拟机与服务器桥接不能上网,vmware虚拟机桥接模式不能上网
- oracle9.2.04下载,Linux AS3.0下安装ORACLE9.2.04
- 第五章 站在巨人的肩膀上
- 微型计算机是啥课,微机课是什么意思
- win10小娜不能使用解决方案
- css3实现3d图片旋转效果
- 关于程序员成长的一点思考
- k8s——flannel网络
- 靶机渗透练习84-The Planets:Earth
- java万年历的设计总结_java万年历设计报告
- QM的计算机专业,PCM5-QM170
- 搁浅争议共同开发_搁浅!
- 盈通rx580游戏高手 bios_RX 5700 XT D6 游戏高手测评:女装大佬重捶出击!