理解:如果一个功能,里面比较复杂,代码量比较多,我们就可以把这个功能分解成多个小的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 CashRegister 10 { 11 public CashRegister() 12 { 13 Tax = 0.06m; 14 } 15 16 private decimal Tax { get; set; } 17 18 public void AcceptPayment(Customer customer, IEnumerable<Product> products, 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 Customer 38 { 39 public void DeductFromAccountBalance(decimal amount) 40 { 41 // deduct from balance 42 } 43 } 44 45 public class Product 46 { 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 CashRegister 10 { 11 public CashRegister() 12 { 13 Tax = 0.06m; 14 } 15 16 private decimal Tax { get; set; } 17 private IEnumerable<Product> Products { get; set; } 18 19 public void AcceptPayment(Customer customer, IEnumerable<Product> 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 Customer 59 { 60 public void DeductFromAccountBalance(decimal amount) 61 { 62 // deduct from balance 63 } 64 } 65 66 public class Product 67 { 68 public decimal Price { get; set; } 69 public decimal AvailableDiscounts { get; set; } 70 } 71 }
我们把AcceptPayment的内部逻辑拆分成了CalculateSubtotal、SubtractDiscounts、AddTax、SubtractFromCustomerBalance四个功能明确且可读性更好的小方法。
这个重构和我们前面讲的“提取方法”和“提取方法对象”如出一辙,尤其是“提取方法”,所以大家只要知道用这种思想重构就行。