影片出租店是《重构:改善既有代码的设计》里面的第一个例子。使用了多种重构方法。
影片出租店:计算每一位顾客的消费金额并打印详单。
操作者告诉程序:顾客租了哪些影片,租期多长,程序便根据租赁时间和影片类型算出费用。影片分为三类:普通片,儿童片和新片。除了计算费用,还要为常客计算积分,积分会根据租片种类是否为新片而有不同。
第1次重构:
- Extract Method: 将switch 提炼到独立函数中
- A: 找出局部变量和参数: rental , ThisAount
- B: 将不被修改的变量当成参数出入到新函数
- C: 如果被修改的只有1个,可以将其变为返回值
- D: 如果不好区分,就全部传引用
- F: 重命名函数内的参数或者变量名
修改后的代码
QString Customer::Statement()
{
double TotalAmout = 0;
int FrequentRenterPoints = 0;
QString result = "Rental Record for " + GetName() + "\n";
for (Rental *rental : GetRentals())
{
double ThisAmount = 0;
ThisAmount = AmountFor(rental);
FrequentRenterPoints++;
if (Movie::NEW_RELEASE == (rental->GetMovie()->GetPriceCode()) &&
rental->GetDaysRented() > 1 )
{
FrequentRenterPoints++;
}
result += "\t" + rental->GetMovie()->GetTitle() + "\t" + QString("%1").arg(ThisAmount) + "\n";
TotalAmout += ThisAmount;
}
result += "Amount owed is " + QString("%1").arg(TotalAmout) + "\n";
result += "You earned " + QString("%1").arg(FrequentRenterPoints) + " frequent renter points";
qDebug() << qPrintable(result) ;
return result;
}
double Customer::AmountFor(Rental *rental)
{
double Result = 0;
switch (rental->GetMovie()->GetPriceCode())
{
case Movie::REGULAR:
Result += 2;
if (rental->GetDaysRented() > 2)
{
Result += (rental->GetDaysRented() - 2)*1.5;
}
break;
case Movie::NEW_RELEASE:
Result += rental->GetDaysRented() * 3;
break;
case Movie::CHILDREN:
Result += 1.5;
if (rental->GetDaysRented() > 3)
{
Result += (rental->GetDaysRented() - 3)*1.5;
}
break;
}
return Result;
}
测试结果: