理解:如果一个功能,里面比较复杂,代码量比较多,我们就可以把这个功能分解成多个小的method,每个方法实现该功能的一个小小的部分,并且方法命名成容易理解,和方法内容相关的名称,更有助于维护和可读性提高。
详解:
重构前代码:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 7 namespace ReflectorDemo 8 { 9 public class CashRegister10 {11 public CashRegister()12 {13 Tax = 0.06m;14 }15 16 private decimal Tax { get; set; }17 18 public void AcceptPayment(Customer customer, IEnumerableproducts, decimal payment)19 {20 decimal subTotal = 0m;21 foreach (Product product in products)22 {23 subTotal += product.Price;24 }25 26 foreach (Product product in products)27 {28 subTotal -= product.AvailableDiscounts;29 }30 31 decimal grandTotal = subTotal * Tax;32 33 customer.DeductFromAccountBalance(grandTotal);34 }35 }36 37 public class Customer38 {39 public void DeductFromAccountBalance(decimal amount)40 {41 // deduct from balance42 }43 }44 45 public class Product46 {47 public decimal Price { get; set; }48 public decimal AvailableDiscounts { get; set; }49 }50 }
我们看到这个AcceptPayment方法,因为现实中AcceptPayment方法不会做这么多的事情。,所以我们通过几次分解将 AcceptPayment拆分成若干个名字有意义且可读性更好的小方法。
重构后代码:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 7 namespace ReflectorDemo 8 { 9 public class CashRegister10 {11 public CashRegister()12 {13 Tax = 0.06m;14 }15 16 private decimal Tax { get; set; }17 private IEnumerableProducts { get; set; }18 19 public void AcceptPayment(Customer customer, IEnumerable products, decimal payment)20 {21 decimal subTotal = CalculateSubtotal();22 23 subTotal = SubtractDiscounts(subTotal);24 25 decimal grandTotal = AddTax(subTotal);26 27 SubtractFromCustomerBalance(customer, grandTotal);28 }29 private void SubtractFromCustomerBalance(Customer customer, decimal grandTotal)30 {31 customer.DeductFromAccountBalance(grandTotal);32 }33 34 private decimal AddTax(decimal subTotal)35 {36 return subTotal * Tax;37 }38 39 private decimal SubtractDiscounts(decimal subTotal)40 {41 foreach (Product product in Products)42 {43 subTotal -= product.AvailableDiscounts;44 }45 return subTotal;46 }47 48 private decimal CalculateSubtotal()49 {50 decimal subTotal = 0m;51 foreach (Product product in Products)52 {53 subTotal += product.Price;54 }55 return subTotal;56 }57 }58 public class Customer59 {60 public void DeductFromAccountBalance(decimal amount)61 {62 // deduct from balance63 }64 }65 66 public class Product67 {68 public decimal Price { get; set; }69 public decimal AvailableDiscounts { get; set; }70 }71 }
我们把AcceptPayment的内部逻辑拆分成了CalculateSubtotal、SubtractDiscounts、AddTax、SubtractFromCustomerBalance四个功能明确且可读性更好的小方法。
这个重构和我们前面讲的“提取方法”和“提取方法对象”如出一辙,尤其是“提取方法”,所以大家只要知道用这种思想重构就行。