1.3重構-第一章

搬移“金額計算”代碼

         接1.2,觀察amountFor()(計算金額)使用了來自Rental(租賃實體)類的信息,卻沒有使用來自Customer類的信息。

         這就使我們懷疑它是否被放錯了位置。絕大多數情況下,函數應該放在它所使用的數據的所屬對象內,所以amountFor()應該從Customer(顧客實體)類中移到Rental(租賃實體)類去。

         爲了這麼做,我要運用Move Method(搬移函數)。首先把代碼複製到Rental類,調整代碼使之適應新家,然後重新編譯。

class Rental...
// 計算金額
public double getCharge() {
	double result = 0;
	switch (get_movie().get_priceCode()) {
	case Movie.REGULAR:
		result += 2;
		if (get_dayRented() > 2) {
			result += (get_dayRented() - 2) * 1.5;
		}
		break;
	case Movie.NEW_RELEASE:
		result += get_dayRented() * 3;
		break;
	case Movie.CHILDRENS:
		result += 1.5;
		if (get_dayRented() > 3) {
			result += (get_dayRented() - 3) * 1.5;
		}
		break;
	}
	return result;
}

         在這個例子裏,“適應新家”意味着要去掉參數。此外,還要在搬移的過程中更改函數名稱。然後改變Customer.amountFor()函數內容,使它委託調用新的函數即可:

class Customer...
private double amountFor(Rental aRental){
  return aRental.getCharge();
}

         然後編譯並測試,看看有沒有破壞什麼東西。

         接下來找到程序中對於舊函數的引用點,並修改它們,讓它們改用新函數。

public String statement(){
	double totalAmount = 0;//總金額
	int frequentRenterPoints = 0;//本次總積分
	
	Enumeration<Rental> rentals = _rentals.elements();
	// 租賃備案
	String result = "Rental Record for "+getName()+"\n";
	while(rentals.hasMoreElements()){
		double thisAmount = 0;
		Rental each = rentals.nextElement();
		
		// 計算金額
		thisAmount = each.getCharge();
		
		// 常規積分累加
		frequentRenterPoints++;
		// 特殊新書積分計算
		if (each.get_movie().get_priceCode() == Movie.NEW_RELEASE &&
			each.get_dayRented() > 1) {
			frequentRenterPoints++;
		}
		
		// 顯示憑條
		result += "\t"+each.get_movie().get_title()+"\t"+String.valueOf(thisAmount)+"\n";
		totalAmount += thisAmount;
	}
	
	// 組裝頁腳
	result += "Amount owed is "+String.valueOf(totalAmount)+"\n";
	result += "You earned "+String.valueOf(frequentRenterPoints)+" frequent renter points";
	return result;
}
最終的UML

         至此,對於Rental.getCharge()的修改暫時終止,讓我們回到Customer.statement()函數。通過觀察,發現thisAmount(臨時變量-某一類影片的總金額)如今變的多餘了。他接受each.getCharge()的執行結果,然後就不會再有任何改變。所以可以運用Replace Temp with Query(以查詢取代臨時變量)把thisAmount除去:

class Customer...
public String statement(){
	double totalAmount = 0;//總金額
	int frequentRenterPoints = 0;//本次總積分
	
	Enumeration<Rental> rentals = _rentals.elements();
	// 租賃備案
	String result = "Rental Record for "+getName()+"\n";
	while(rentals.hasMoreElements()){
		Rental each = rentals.nextElement();
		
		// 常規積分累加
		frequentRenterPoints++;
		// 特殊新書積分計算
		if (each.get_movie().get_priceCode() == Movie.NEW_RELEASE &&
			each.get_dayRented() > 1) {
			frequentRenterPoints++;
		}
		
		// 顯示憑條
		result += "\t"+each.get_movie().get_title()+"\t"+String.valueOf(each.getCharge())+"\n";
		totalAmount += each.getCharge();
	}
	
	// 組裝頁腳
	result += "Amount owed is "+String.valueOf(totalAmount)+"\n";
	result += "You earned "+String.valueOf(frequentRenterPoints)+" frequent renter points";
	return result;
}

         修改完事,立即編譯測試,保證沒有破壞任何東西。

         臨時變量往往會引發問題,他們會導致大量參數被傳來傳去,而其實完全沒有這種必要。當然除去臨時變量也會引發問題,如上述修改,會導致查詢兩次的性能問題,但這個問題可以在Rental中很好的被優化,此處不做說明。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章