實例代碼:
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for * " + getName() + "\n";
while(rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental)rentals.nextElement(); //取得一筆租借記錄
switch(each.getMovie().getPriceCode()) { //取得影片出租價格
case Movie.REGULAR: //普通片
thisAmount += 2;
if(each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE: //新片
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS: //兒童片
thisAmount += 1.5;
if(each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
// add frequent renter points(累加常客積點)
frequentRenterPoints ++;
if((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&
each.getDaysRented() > 1)
frequentRenterPoints ++;
result += "\t" + each.getMovie().getTitle() + "\t" +
String.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
}
// add footer lines(結尾打印)
result += "Amount owed is " + String.valueOf(totalAmount) + " \n";
result += "You earned " + String.valueOf(frequentRenterPoints) +
"frequent renter points";
return result;
}
第一步驟是找出代碼的邏輯泥團并運用Extract Method(110).本例一個明顯的邏輯泥團就是switch語句,把它提煉(extract)到獨立函數中似乎比較好.
首先我得在這段代碼里頭找出函數內的局部變量(local
variables)和參數(parameters).我找到了兩個:each和thisAmount,前者并未被修改,后者會被修改.任何不會被修改的
變量都可以被我當成參數傳入新的函數,至于會被修改的變量就需格外小心.如果只有一個變量會被修改,我可以把它當作返回值.thisAmount是個臨時
變量,其值在每次循環起始處被設為0,并且在switch語句之前不會改變,所以我可以把新函數的返回值賦予它.
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for * " + getName() + "\n";
while(rentals.hasMoreElements()) {
double thisAmount = 0;
Rental each = (Rental)rentals.nextElement(); //取得一筆租借記錄
thisAmount = amountFor(each);
// add frequent renter points(累加常客積點)
frequentRenterPoints ++;
if((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&
each.getDaysRented() > 1)
frequentRenterPoints ++;
result += "\t" + each.getMovie().getTitle() + "\t" +
String.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
}
// add footer lines(結尾打印)
result += "Amount owed is " + String.valueOf(totalAmount) + " \n";
result += "You earned " + String.valueOf(frequentRenterPoints) +
"frequent renter points";
return result;
}
public double amountFor(Rental each) {
double thisAmount = 0;
switch(each.getMovie().getPriceCode()) { //取得影片出租價格
case Movie.REGULAR: //普通片
thisAmount += 2;
if(each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE: //新片
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS: //兒童片
thisAmount += 1.5;
if(each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
return thisAmount;
}
現在,已經把原本的函數分為兩塊,可以分別處理它們.我不喜歡amountFor()內的某些變量名稱,現在是修改它們的時候.
下面是原本的代碼:
public double amountFor(Rental each) {
double thisAmount = 0;
switch(each.getMovie().getPriceCode()) { //取得影片出租價格
case Movie.REGULAR: //普通片
thisAmount += 2;
if(each.getDaysRented() > 2)
thisAmount += (each.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE: //新片
thisAmount += each.getDaysRented() * 3;
break;
case Movie.CHILDRENS: //兒童片
thisAmount += 1.5;
if(each.getDaysRented() > 3)
thisAmount += (each.getDaysRented() - 3) * 1.5;
break;
}
return thisAmount;
}
下面是易名后的代碼:
public double amountFor(Rental aRental) {
double result = 0;
switch(aRental.getMovie().getPriceCode()) { //取得影片出租價格
case Movie.REGULAR: //普通片
result += 2;
if(aRental.getDaysRented() > 2)
result += (aRental.getDaysRented() - 2) * 1.5;
break;
case Movie.NEW_RELEASE: //新片
result += aRental.getDaysRented() * 3;
break;
case Movie.CHILDRENS: //兒童片
result += 1.5;
if(aRental.getDaysRented() > 3)
result += (aRental.getDaysRented() - 3) * 1.5;
break;
}
return result;
}