设计原则:消除Switch...Case的过程,可能有点过度设计了。

备注

不要重复自己,也不要重复别人,一旦养成了“拷贝和粘贴”的习惯,写程序的时候非常容易导致重复,好在一直暗示自己要稍后进行重构,本文给出一个重构的示例。

需求

需求:按照年、月和日显示销售数据,根据不同的周期类型,有三个问题需要注意:

  1. 默认的日期范围不同
  2. 图表中显示的格式不同
  3. 默认的模拟数据不同(发布环境会使用真实的数据)

如下图:

 

第一遍代码(重复的代码)

最爱的拷贝和粘贴。

默认的日期范围不同

 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 }

备注

完成第一遍后,差点不想进行重构了,战胜自己非常不容易,继续努力。

 

posted on 2013-09-03 23:40  幸福框架  阅读(5549)  评论(21编辑  收藏  举报

导航

我要啦免费统计