本系列来自《java 重构改善既有代码的设计》一书
当对局部变量的引用无法使用Extract Method的时候,可以考虑将这个函数放入到一个单独的对象中去,如此一来,局部变量就变成了对象的字段,然后就可以在同一对象中将这个大型函数分解成小型函数。
如:在Order类中:
package com.xuzengqiang.ssb.movie;
public class Order {
// .....
private double price() {
double primaryBasePrice;
double secondaryBasePrice;
double tertiaryBasePrice;
// do something
return 1.0;
}
}
这个时候就可以将price抽取出来作为一个单独的类,此时里面的局部变量就变成了这个类里面的字段。
package com.xuzengqiang.ssb.movie;
public class PriceCalculator {
private final Test test;
private double primaryBasePrice;
private double secondaryBasePrice;
private double tertiaryBasePrice;
public PriceCalculator(Test test) {
this.test = test;
}
public double price() {
double result = 0.0;
// do something
return result;
}
// other ...
}
做法:
1、建立一个新的class,根据待被处理的函数的用途给其命名。
2、在新的class中建立一个final值域,用来保存原先大型函数的对象,称为源对象。同时针对原函数的每个临时变量和每个参数,在新class中建立一个个对应的值域保存。
3、在新的class中建立一个构造函数,接收原对象及原函数的所有的参数作为参数。
4、在新的class中建立一个对应的方法,如上例中的price(),并将原函数中的代码拷贝进来。
5、编译,在原函数中利用new 新class().price()执行该方法。
例子:
public int gamma(int inputValue, int quantity, int yearToDate) {
int importantValue1 = inputValue * quantity + delta();
int importantValue2 = inputValue * yearToDate + 100;
if ((yearToDate - importantValue1) > 100) {
importantValue2 -= 20;
}
int importantValue3 = importantValue2 * 7;
return importantValue3 - 2 * importantValue1;
}
修改:
新建一个class,在这个class中提供一个final值域保存原先的对象,将源函数中的每一个参数和每一个临时变量,也以一个个值域逐一保存。
Gamma:
private final Test test;
private int inputValue;
private int quantity;
private int yearToDate;
private int importantValue1;
private int importantValue2;
private int importantValue3;
提供对应的构造函数
public Gamma(Test test, int inputValue, int quantity, int yearToDate) {
this.test = test;
this.inputValue = inputValue;
this.quantity = quantity;
this.yearToDate = yearToDate;
}
拷贝原gamma中的方法移动到新class中。整理之后就变成了:
package com.xuzengqiang.ssb.movie;
public class Gamma {
private final Test test;
private int inputValue;
private int quantity;
private int yearToDate;
private int importantValue1;
private int importantValue2;
private int importantValue3;
public Gamma(Test test, int inputValue, int quantity, int yearToDate) {
super();
this.test = test;
this.inputValue = inputValue;
this.quantity = quantity;
this.yearToDate = yearToDate;
}
public int execute() {
importantValue1 = inputValue * quantity + test.delta();
importantValue2 = inputValue * yearToDate + 100;
if ((yearToDate - importantValue1) > 100) {
importantValue2 -= 20;
}
importantValue3 = importantValue2 * 7;
return importantValue3 - 2 * importantValue1;
}
}
原函数中的gamma方法就变成了:
public int gamma(int inputValue, int quantity, int yearToDate) {
return new Gamma(this,inputValue,quantity,yearToDate).execute();
}
当然你还可以继续对execute()中的方法进行重构。