- A+
八. 重构5:继续将相应的方法进行移动(Move Method)
通过“代码重构与单元测试——“提取方法”重构(三) ”至“代码重构与单元测试——使用“以查询取代临时变量”再次对Statement()方法进行重构(七) ”这几篇文章的几次重构之后,再次对充电宝计费项目的代码进行全局性的观察与分析,我们发现在Rental类中的GetAmount()与GetFrequentRenterPoints()方法中的代码对PowerBank类有较大的依赖。因为这两个方法都只用到了Rental类中的RentedTime属性,而多次用到了PowerBank中的属性或字段。通过上面的分析,我们认为将这两个方法中的代码移到PowerBank类中显得更为合理。接下来,我们继续进行这两个方法的重构——将该部分代码移动到PowerBank类中。
1. 这次跟之前的“代码重构与单元测试——将方法移到合适[依赖]的类中(六) ”文章中的移动方法不同,这次要在Rental中保留这两个方法的声明,在PowerBank类中创建新的同方法名称的方法,将方法的内容移到PowerBank中后,在Rental中调用PowerBank类中的方法。下面是我们经过这次重构后我们PowerBank类中的内容。其中红色的代码是我们移过来的代码,而斜体的代码,是参数需要从外界传入。具体代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LeasePowerBank { /// <summary> /// 充电宝类 /// </summary> public class PowerBank { //地段人流量种类 public static int LowTraffic = 0;//低人流量地段 public static int MiddleTraffic = 1;//中人流量地段 public static int HighTraffic = 2; //高人流量地段 public int PriceCode; //价格代码 public string Title;//充电宝名称 public PowerBank(string title,int priceCode) { PriceCode = priceCode; Title = title; } /// <summary> /// 根据消费金额,充电宝所处地段,进行积分计算 /// </summary> /// <param name="RentedTime">租赁时间</param> /// <returns></returns> public int GetFrequentRenterPoints(int RentedTime) { int frequentRenterPoints = 0; decimal amount = GetAmount(RentedTime); //计算积分 if (this.PriceCode == HighTraffic && RentedTime > 4) { frequentRenterPoints += (int)Math.Ceiling(amount * 1.5M); } else frequentRenterPoints += (int)Math.Ceiling(amount); return frequentRenterPoints; } /// <summary> /// 根据充电宝订单,计算总金额 /// </summary> /// <param name="RentedTime">租赁时间</param> /// <returns></returns> public decimal GetAmount(int RentedTime) { decimal amount = 0M; switch (this.PriceCode) { case 0: amount = RentedTime; if (RentedTime > 12) { amount = 12; } break; case 1: amount = RentedTime * 3; if (RentedTime > 24) { amount = 24; } break; case 2: amount = RentedTime * 5; if (RentedTime > 50) { amount = 50; } break; default: break; } return amount; } } }
2.将相应的方法代码移动PowerBank类中后,在Rental中我们需要对其进行调用。在调用相应的方法时传入相应的参数即可。如下图,图中代码就是经过这次重构之后的Rental类的代码,红框中的代码就是对PowerBank中新添加的方法的调用。代码如下所示:
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; } /// <summary> /// 根据消费金额,充电宝所处地段,进行积分计算 /// </summary> /// <returns></returns> public int GetFrequentRenterPoints() { return this.Power.GetFrequentRenterPoints(RentedTime); } /// <summary> /// 根据充电宝订单,计算总金额 /// </summary> /// <returns></returns> public decimal GetAmount() { return this.Power.GetAmount(RentedTime); } } }
3. 我们的测试用例依然不变。在每次重构后我们都需要调用上述的测试用例来检查重构是否产生了副作用。现在我们的类间的依赖关系没怎么发生变化,只是相应类中的方法有些变化。在Visual Studio 2019的菜单栏上找到“测试-->运行所有测试”菜单项。或者在“测试资源管理器中”选择 “在视图中运行所有测试”按钮, 运行测试用例。监测重构的结果是否正确。如下图。