六、重构3:将方法移到合适[依赖]的类中
经过之前的重构(见文章 代码重构与单元测试——“提取方法”重构(三) 与代码重构与单元测试——对方法的参数进行重构(五) ),我们从Statement()方法中提取了两个方法。观察这两个重构后的方法我们不难看出,这两个封装出来的新方法都只需要一个参数,这个参数就是Rental类的对象。也就是这两个方法都依赖于Rental类,而对该方法所在的当前类不太依赖。之所以会这种情况,是因为这两个方法放错了地方,因为这两个方法放在Customer类中但不依赖与Customer类而依赖于Rental类,那就足以说明这两个方法应该放在Rental类中。
1.经过简单的分析后,我们就可以决定要将新提取的方法放到Rental类中,并且方法的参数去掉。因为方法在Rental类中,所以在方法中直接使用this即可。将计算金额的方法和计算积分的方法移到Rental类中。
2. 在Visual Studio 2019代码编辑器中打开Rental.cs文件,将GetAmount和GetFrequentRenterPoints方法从Customer.cs文件中移到Rental.cs文件中。具体代码如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LeasePowerBank
{
/// <summary>
/// 租赁类
/// </summary>
public class Rental
{
public PowerBank Power ; //充电宝名称
public int RentedTime;//租赁时间
public Rental(PowerBank powerbk,int rentedTime)
{
Power = powerbk;
RentedTime = rentedTime;
}
public int GetFrequentRenterPoints()
{
int frequentRenterPoints = 0;
decimal amount = GetAmount();
//计算积分
if (this.Power.PriceCode == PowerBank.HighTraffic && this.RentedTime > 4)
{
frequentRenterPoints += (int)Math.Ceiling(amount * 1.5M);
}
else
frequentRenterPoints += (int)Math.Ceiling(amount);
return frequentRenterPoints;
}
/// <summary>
/// 根据充电宝订单,计算总金额
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public decimal GetAmount()
{
decimal amount = 0M;
switch (this.Power.PriceCode)
{
case 0:
amount = this.RentedTime;
if (this.RentedTime > 12)
{
amount = 12;
}
break;
case 1:
amount = this.RentedTime * 3;
if (this.RentedTime > 24)
{
amount = 24;
}
break;
case 2:
amount = this.RentedTime * 5;
if (this.RentedTime > 50)
{
amount = 50;
}
break;
default:
break;
}
return amount;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LeasePowerBank
{
/// <summary>
/// 客户类
/// </summary>
public class Customer
{
string Name;//用户名称
public List<Rental> listRentals=new List<Rental>();//用户租赁的充电宝
public Customer(string name)
{
Name = name;
}
public void AddRental(Rental rental)
{
listRentals.Add(rental);
}
public string Statement()
{
decimal totalAmount = 0M; //总金额
int frequentRenterPoints = 0; //用户积分
string result = $"{Name} 的租赁账单:
";
foreach (var item in listRentals)
{
decimal amount = item.GetAmount();//总价计算
totalAmount += amount;
frequentRenterPoints = item.GetFrequentRenterPoints();
}
result += $"总金额为:{totalAmount}
";
result += $"你本次获得了:{frequentRenterPoints}积分 ";
return result;
}
}
}
4. 在Visual Studio 2019中打开测试项目LeasePowerBankTest中的UnitTest1.cs测试类文件,对单元测试中的测试用例我们也要进行一下修改。将调用Customer类中的方法,修改为调用Rental类中的方法。代码如下:
[TestMethod]
public void ValidGetAmountTest()
{
double expected = 5;
//创建用户
var customer = new Customer("张三");
//创建充电宝
PowerBank regularPowerBank = new PowerBank("低-充电宝", PowerBank.LowTraffic);
//创建租赁数据
var rental1 = new Rental(regularPowerBank, 5);
// Act
double actual = (double)rental1.GetAmount();
// Assert
Assert.AreEqual(expected,actual,0.001, $"总金额计算错误,实际计算金额{actual},期望金额:{expected}");
}
[TestMethod]
public void ValidGetFrequentRenterPointsTest()
{
int expected = 5;
//创建用户
var customer = new Customer("张三");
//创建充电宝
PowerBank regularPowerBank = new PowerBank("低-充电宝", PowerBank.LowTraffic);
//创建租赁数据
var rental1 = new Rental(regularPowerBank, 5);
// Act
int actual = rental1.GetFrequentRenterPoints();
// Assert
Assert.AreEqual(expected, actual, 0.001, "积分计算错误");
}
5. 在Visual Studio 2019的菜单栏上找到“测试-->运行所有测试”菜单项。或者在“测试资源管理器中”选择 “在视图中运行所有测试”按钮, 运行测试用例。监测重构的结果是否正确。如下图。