重构手法–对象内
Extract Method(提炼函数)
将一段需要加注释的函数放进一个独立函数中,并让函数名称解释该函数的用途,因为函数约简短被复用的机会就越大。
重构前的代码:
void printOwing(){
Enumeration e = _order.elements();
double outstanding = 0.0;
//print banner
System.out.println("*************************");
System.out.println("***** Customer Owes *****");
System.out.println("*************************");
//calculate outstanding
while(e.hasMoreElements()){
Order each = (Order)e.nextElement();
outstanding += each.getAmount();
}
//print details
System.out.println("name:"+_name);
System.out.println("amount"+outstanding);
}
重构后的代码:
void printOwing(){
printBanner();
printDetails(getOutstanding())
}
void printBanner(){
System.out.println("*************************");
System.out.println("***** Customer Owes *****");
System.out.println("*************************");
}
double getOutstanding(){
Enumeration e = _order.elements();
double result = 0.0;
while(e.hasMoreElements()){
Order each = (Order)e.nextElement();
result += each.getAmount();
}
return result;
}
void printDetails(double outstanding){
System.out.println("name:"+_name);
System.out.println("amount"+outstanding);
}
Inline Method(内联函数)
过分提炼的函数,用函数体代替该函数更能让代码清晰
重构前的代码:
int getRating(){
return (moreThanFiveLateDeliveries()) ? 2 : 1;
}
boolean moreThanFiveLateDeliveries(){
return _numberOfLateDeliveries > 5;
}
重构后的代码:
int getRating(){
return (_numberOfLateDeliveries > 5) ? 2 : 1;
}
Inline Temp(内联临时变量)
只被一个简单表达式赋值一次的临时变量,不如把它替换为赋值的那个表达式本身
重构前的代码:
double basePrice = anOrder.basePrice();
return (basePrice > 1000)
重构后的代码:
return (anOrder.basePrice() > 1000);
Replace Temp with Query(以查询取代临时变量)
将表达式提炼到一个独立函数中,去掉保存该表达式结果的临时变量,为了该表达式可以被复用。
重构前的代码:
double basePrice = _quantity * _itemPrice;
if(basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
重构后的代码:
if(basePrice() > 1000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
...
double basePrice(){
return _quantity * _itemPrice;;
}
Introduce Explaining Variable(引入解释性变量)
当表达式比较复杂时,把表达式的结果放进临时变量里,个人理解这个重构手法没啥用
重构前的代码:
if((platform.toUpperCase().indexOf("MAC") > -1) &&
(browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0){
//do something
}
利用该重构手法重构后的代码:
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if(isMacOs && isIEBrowser && wasInitialized() && wasResized){
//do something
}
个人感觉使用Extract Method(提炼函数)方法会更好:
if(isMacOs() && isIEBrowser() && wasInitialized() && wasResized()){
//do something
}
boolean isMacOs(){
return platform.toUpperCase().indexOf("MAC") > -1;
}
boolean isIEBrowser(){
return browser.toUpperCase().indexOf("IE") > -1;
}
boolean wasResized(){
return resize > 0;
}
Split Temporary Variable(分解临时变量)
一个临时变量只承担一种意义的变量赋值,如果被多种含义的变量赋值多次就会影响代码阅读
重构前的代码:
double temp = 2 * (_height + _width);
System.out.println(temp);
temp = _height * _width;
System.out.println(temp);
重构后的代码:
final double temp = 2 * (_height + _width);
System.out.println(temp);
final double area = _height * _width;
System.out.println(temp);
Remove Assignments to Parameters(移除对参数的赋值)
用临时变量取代直接对参数进行赋值的操作,为了代码便于阅读
重构前的代码:
int discount(int inputVal, int quantity, int yearToDate){
if(inputVal > 50)
inputVal -= 2;
return inputVal;
}
重构后的代码:
int discount(int inputVal, int quantity, int yearToDate){
int result = inputVal;
if(inputVal > 50)
result -= 2;
return result;
}
Replace Method with Method Object(以函数对象取代函数)
如果一个比较大的函数里局部变量很多,导致无法直接对该函数进行Extract Method(提炼),这时候就可以把该函数放进一个单独对象里再提炼
重构前的代码:
class Account{
int gamma(int inputVal, int quantity, int yearToDate){
int importantValue1 = (inputVal * quantity) + delta();
int importantValue2 = (inputVal * yearToDate) + 100;
if((yearToDate - importantValue) > 100){
importantValue2 -= 20;
}
int importantValue3 = importantValue2 * 7;
return importantValue3 - 2 * importantValue1;
}
}
重构后的代码:
class Gamma{
private final Account _account;
private int inputVal;
private int quantity;
private int yearToDate;
private int importantValue1;
private int importantValue2;
private int importantValue3;
Gamma(Account source,int inputValArg, int quantityArg,int yearToDateArg){
_account = source;
inputVal = inputValArg;
quantity = quantityArg;
yearToDate = yearToDateArg;
}
int compute(){
importantValue1 = (inputVal * quantity) + _account.delta();
importantValue2 = (inputVal * yearToDate) + 100;
importantThing();
importantValue3 = importantValue2 * 7;
return importantValue3 - 2 * importantValue1;
}
void importantThing(){
if((yearToDate - importantValue) > 100){
importantValue2 -= 20;
}
}
}
class Account{
int gamma(int inputVal, int quantity, int yearToDate){
return new Gamma(this, inputVal, quantity, yearToDate),compute();
}
}
Substitute Algorithm(替换算法)
将某个算法替换为另一个更清晰的算法
重构前的代码:
String foundPerson(String[] people){
for(int i = 0;i < people.lenght; i++){
if(people[i].equals("Don")){
return "Don";
}
if(people[i].equals("John")){
return "John";
}
if(people[i].equals("Kent")){
return "Kent";
}
}
return "";
}
重构后的代码:
String foundPerson(String[] people){
List candidates = Arrays.asList(new String[] {"Don","John","Kent"});
for(int i = 0;i < people.lenght; i++){
if(candidates.contains(people[i])){
return people[i];
}
}
return "";
}