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中很好的被优化,此处不做说明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值