重构
《重构:改善既有代码的设计》 读后笔记
java程序员必读书籍之一。
目前只看了第一遍 觉得非常受用
所以整理了一些能经常使用到的重构方法。
一 重新组织函数
1 提炼函数
将代码放入一个单独的函数中,用函数名解释该函数的用途。
重构前代码
void printOwing(double amount){
printBanner();
System.out.println("name:" + "_name");
System.out.println("amount:" + amount);
}
重构后代码
void printOwing(double amount){
printBanner();
printDetails(amount);
}
void printOwing(double amount){
System.out.println("name:" + "_name");
System.out.println("amount:" + amount);
}
2 简化函数调用
重构前
String getMessage(int status){
if(status != 0 &&status != -1){
return "程序错误";
}
if(status==0){
成功状态下执行的代码
}else{
失败状态下执行的代码
}
}
重构后
String getSuccessMessage(){
final int STATUS = 0; //直接赋值成功的状态
...无关代码
}
String getFailMessage(){
final int STATUS = -1; //直接赋值失败的状态
...无关代码
}
对比调用
// 重构前
getMessage(0);
// 重构后
getSuccessMessage(); //无需传参
3 函数对象取代函数
将一个大型函数放进一个单独对象中,如此一来局部变量就成了对象内的字段。
然后可以在这个对象中将这个大型函数分解为多个小型函数。
重构前代码
void bigMethod(){
// 局部变量 N个
// 如果分解函数 局部变量只能从形参传递
冗长代码好几百行...
}
重构后代码
class BigMethodEntity{
//成员变量 N个
int aaa;
int bbb;
String ccc;
//所有方法共享成员变量
void bigMethodMain(){ // 分解函数 结构清晰
smallMethodA();
smallMethodB();
smallMethodC();
}
void smallMethodA(){}
void smallMethodB(){}
void smallMethodC(){}
}
对比调用
// 重构前
bigMethod();
// 重构后
new BigMethodEntity().bigMethodMain();
4 替换算法
替换一个更清晰的算法
替换前代码
String foundPerson(String[] people){
for(String item : people){
if("Don".equals(item)){
return "Don";
}
if("Bon".equals(item)){
return "Bon";
}
if("Kon".equals(item)){
return "Kon";
}
if("Son".equals(item)){
return "Son";
}
}
return "无对应";
}
替换后代码
String foundPerson(String[] people){
List<String> listString = Arrays.asList(new String[]("Don","Bon","Kon","Son"));
for(String item : people){
if(listString.contains(item)) return people;
}
return "无对应";
}
二 简化条件表达式
5 合并条件表达式
将这些判断合并为一个条件表达式,并将这些条件表达式提炼成为一个独立函数。
重构前
int ifMethod(){
if (one_int < 2) return 0;
if (two_long > 9) return 0;
if (three_char == 'a') return 0;
}
重构后
int ifMethod(){
if (isTrue())return 0;
}
6 拆分条件表达式
将杂乱判断语句分解为多个条件表达式,提高阅读性。
重构前
int ifMethod(){
if (one_int < 2 && two_long > 9 && three_char == 'a') return 0;
}
重构后
int ifMethod(){
boolean b1 = isTrue1();
boolean b1 = isTrue2();
boolean b3 = isTrue3();
if ( b1 && b2 && b3) return 0;
}
7 卫语句代替嵌套条件表达式
函数中的条件逻辑很难以看清正常的执行路径。
例
int getAmount(){
if () {
if(){
if(){
} else if{
}
}
if(){
if(){
}
}
}
}
重构后
int getAmount(){
if (isTrue1()) return getAmountA();
if (isTrue2()) return getAmountB();
if (isTrue3()) return getAmountC();
return getAmountNormal();
}
8 多态取代条件表达式
这种方式的好处:
如果同一组条件表达式在许多地点出现,且此时你想添加
一种新类型,那就必须更新这组表达式出现的所有地点。
如果使用多态只需要新建一个子类。
重构前
if () {
if(){
if(){
执行代码一
} else if{
执行代码二
}else{
执行代码三
}
}
if(){
if(){
执行代码四
}else {
执行代码五
}
}
执行代码默认
}
采用多态取代
// 把执行代码抽取到类中
// 而且每一个类都实现 IfDemo
// 执行代码一 被抽取成类
public interface IfDemo{
public void ifMethod();
}
// 执行代码二 被抽取成类
public class Two implement IfDemo {
public void ifMethod(){
执行代码二
}
}
省略执行代码三四五抽取成类的过程...
// 执行代码五 被抽取成类
public class Five implement IfDemo {
public void ifMethod(){
执行代码五
}
}
// 执行代码默认 被抽取成类
public class Default implement IfDemo {
public void ifMethod(){
执行代码默认
}
}
重构后
switch(type){ // type可以使用 1 基本数据类型 2 字符串 3 枚举类型
case xxx: new One().ifMethod();
case xxx: new Two().ifMethod();
case xxx: new Three().ifMethod();
case xxx: new Four().ifMethod();
case xxx: new Five().ifMethod();
default: new Default().ifMethod();
}
// 此种方式的好处就是 如果新增或修改 新的if逻辑 只需要修改if类
// 可读性良好 逻辑清晰
具体参见策略模式或状态模式