备注
不要重复自己,也不要重复别人,一旦养成了“拷贝和粘贴”的习惯,写程序的时候非常容易导致重复,好在一直暗示自己要稍后进行重构,本文给出一个重构的示例。
需求
需求:按照年、月和日显示销售数据,根据不同的周期类型,有三个问题需要注意:
- 默认的日期范围不同
- 图表中显示的格式不同
- 默认的模拟数据不同(发布环境会使用真实的数据)
如下图:
第一遍代码(重复的代码)
最爱的拷贝和粘贴。
默认的日期范围不同
1 private void ResetStartDateAndEndDate() 2 { 3 this.EndDate = DateTime.Now; 4 5 switch (_currentCircle) 6 { 7 case "日": 8 this.StartDate = this.EndDate.AddMonths(-1); 9 break; 10 case "月": 11 this.StartDate = this.EndDate.AddMonths(-12); 12 break; 13 case "年": 14 this.StartDate = this.EndDate.AddMonths(-12 * 3); 15 break; 16 } 17 18 this.StartDate = this.StartDate.AddDays(1); 19 }
图表中显示的格式不同
1 public string DisplayDate 2 { 3 get 4 { 5 switch (this.Cycle) 6 { 7 case "日": 8 return this.Date.ToString("yyyy-MM-dd"); 9 case "月": 10 return this.Date.ToString("yyyy-MM"); 11 case "年": 12 return this.Date.ToString("yyyy"); 13 default: 14 throw new InvalidOperationException("周期类型不匹配"); 15 } 16 } 17 }
默认的模拟数据不同
1 public IEnumerable<SalesViewModel> Find(string cycle, DateTime startDate, DateTime endDate) 2 { 3 switch (cycle) 4 { 5 case "日": 6 return new List<SalesViewModel> 7 { 8 new SalesViewModel{ Date = DateTime.Now.AddDays(-2).AddDays(1), Total = 100, Cycle = cycle }, 9 new SalesViewModel{ Date = DateTime.Now, Total = 200, Cycle = cycle } 10 }; 11 case "月": 12 return new List<SalesViewModel> 13 { 14 new SalesViewModel{ Date = DateTime.Now.AddMonths(-2).AddDays(1), Total = 100, Cycle = cycle }, 15 new SalesViewModel{ Date = DateTime.Now, Total = 200, Cycle = cycle } 16 }; 17 case "年": 18 return new List<SalesViewModel> 19 { 20 new SalesViewModel{ Date = DateTime.Now.AddYears(-2).AddDays(1), Total = 100, Cycle = cycle }, 21 new SalesViewModel{ Date = DateTime.Now, Total = 200, Cycle = cycle } 22 }; 23 default: 24 return new List<SalesViewModel>(); 25 } 26 }
第二遍代码(消除重复)
“门面类型+多态+私有内部类”消除重复
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using System.Collections.Generic; 12 13 namespace Marking.Dashboard.Infrastructures 14 { 15 public static class CycleTypeHelper 16 { 17 private static Dictionary<string, CycleType> _CycleTypeMaps = new Dictionary<string, CycleType> 18 { 19 { "日", new DayCycleType() }, 20 { "月", new MonthCycleType() }, 21 { "年", new YearCycleType() } 22 }; 23 24 public static IEnumerable<string> CircleTypes 25 { 26 get 27 { 28 return _CycleTypeMaps.Keys; 29 } 30 } 31 32 public static DateTime GetDefaultStartDate(string cycleType, DateTime endDate) 33 { 34 return _CycleTypeMaps[cycleType].GetDefaultStartDate(endDate); 35 } 36 37 public static string GetDisplayDateString(string cycleType, DateTime date) 38 { 39 return _CycleTypeMaps[cycleType].GetDisplayDateString(date); 40 } 41 42 public static IEnumerable<DateTime> SimulateDates(string cycleType, DateTime startDate, DateTime endDate) 43 { 44 return _CycleTypeMaps[cycleType].SimulateDates(startDate, endDate); 45 } 46 47 private abstract class CycleType 48 { 49 public abstract DateTime GetDefaultStartDate(DateTime endDate); 50 51 public abstract string GetDisplayDateString(DateTime date); 52 53 public abstract IEnumerable<DateTime> SimulateDates(DateTime startDate, DateTime endDate); 54 } 55 56 private class YearCycleType : CycleType 57 { 58 public override DateTime GetDefaultStartDate(DateTime endDate) 59 { 60 return endDate.AddMonths(-12 * 3); 61 } 62 63 public override string GetDisplayDateString(DateTime date) 64 { 65 return date.ToString("yyyy"); 66 } 67 68 public override IEnumerable<DateTime> SimulateDates(DateTime startDate, DateTime endDate) 69 { 70 for (var i = startDate; i <= endDate; i = i.AddYears(1)) 71 { 72 yield return i; 73 } 74 } 75 } 76 77 private class MonthCycleType : CycleType 78 { 79 public override DateTime GetDefaultStartDate(DateTime endDate) 80 { 81 return endDate.AddMonths(-12); 82 } 83 84 public override string GetDisplayDateString(DateTime date) 85 { 86 return date.ToString("yyyy-MM"); 87 } 88 89 public override IEnumerable<DateTime> SimulateDates(DateTime startDate, DateTime endDate) 90 { 91 for (var i = startDate; i <= endDate; i = i.AddMonths(1)) 92 { 93 yield return i; 94 } 95 } 96 } 97 98 private class DayCycleType : CycleType 99 { 100 public override DateTime GetDefaultStartDate(DateTime endDate) 101 { 102 return endDate.AddMonths(-1); 103 } 104 105 public override string GetDisplayDateString(DateTime date) 106 { 107 return date.ToString("MM-dd"); 108 } 109 110 public override IEnumerable<DateTime> SimulateDates(DateTime startDate, DateTime endDate) 111 { 112 for (var i = startDate; i <= endDate; i = i.AddDays(1)) 113 { 114 yield return i; 115 } 116 } 117 } 118 } 119 }
备注
完成第一遍后,差点不想进行重构了,战胜自己非常不容易,继续努力。