http://www.cnblogs.com/happyframework/p/3300170.html

目录

备注需求第一遍代码(重复的代码)第二遍代码(消除重复)备注

备注返回目录

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

需求返回目录

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

  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 }

备注返回目录

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

 

消除Switch...Case的过程的更多相关文章

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

    备注 不要重复自己,也不要重复别人,一旦养成了“拷贝和粘贴”的习惯,写程序的时候非常容易导致重复,好在一直暗示自己要稍后进行重构,本文给出一个重构的示例. 需求 需求:按照年.月和日显示销售数据,根据 ...

  2. Java代码消除switch/case,if/else语句的几种实现方式

    转自:https://my.oschina.net/stefanzhlg/blog/372413 我们在平时的编码中,我们经常会遇到这样的情况: 使用过多的switch/case 或者 if else ...

  3. switch case 与 if

    case 在编程中偶尔使用到switch case语句,对于case语句的处理,出现了两种错误,现总结如下: case后必须是常量.布尔类型.字符(不能是字符串): case后如果是‘||’或者‘&a ...

  4. 为什么switch...case语句比if...else执行效率高

    在C语言中,教科书告诉我们switch...case...语句比if...else if...else执行效率要高,但这到底是为什么呢?本文尝试从汇编的角度予以分析并揭晓其中的奥秘. 第一步,写一个d ...

  5. 使用反射+策略模式代替项目中大量的switch case判断

    我这里的业务场景是根据消息类型将离线消息存入mongoDB不同的collection中.其中就涉及到大量的分支判断,为了增强代码的可读性和可维护性,对之前的代码进行了重构. 先对比一下使用反射+策略模 ...

  6. 知识扩展--if...else...与switch...case...的执行原理

    一.简述 编程语言中的条件分支结构有两种:if-else和switch-case,这两种条件分支之间可以相互转换,但是也存在一些区别,那么什么时候该用if-else,什么时候该用switch-case ...

  7. 浅析C/C++中的switch/case陷阱

    浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp #include<iostream> using namespace std; int main(i ...

  8. Java基础之循环语句、条件语句、switch case 语句

    Java 循环结构 - for, while 及 do...while 顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构. Java中有三种主要的循环结构: whi ...

  9. python中Switch/Case实现

    学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现.所以不妨自己来实现Switch/Case功能. 方法一 通过字典实现 ...

随机推荐

  1. android之【本地通知Notification】

    public class NotificationTest extends Activity { static final int NOTIFICATION_ID = 0x1123; @Overrid ...

  2. ArcEngine载入中SDE问题栅格数据

    当直接加载矢量数据到IFeatureWorkspace接口可,但是,在装载门格当要传送的数据IRasterWorkspaceEx接口. 效果如下面的,对可以被添加到双击Globe在. watermar ...

  3. .net mvc mssql easyui treegrid 及时 编辑 ,支持拖拽

    这里提到了,1个问题,怎么扩展 Easyui 参见: http://blog.csdn.net/chenkai6529/article/details/17528833 @{ ViewBag.Titl ...

  4. Swift语言指南(九)--基本运算符

    原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...

  5. java中Integer包装类的具体解说(java二进制操作,全部进制转换)

    程序猿都非常懒,你懂的! 今天为大家分享的是Integer这个包装类.在现实开发中,我们往往须要操作Integer,或者各种进制的转换等等.我今天就为大家具体解说一下Integer的使用吧.看代码: ...

  6. 使用Net.Mail、CDO组件、JMail组件三种方式发送邮件

    原文:使用Net.Mail.CDO组件.JMail组件三种方式发送邮件 一.使用Net.Mail 需要服务器认证,大部分服务器端口为25. { MailMessage mailMsg = mailMs ...

  7. Installshield设置feature为必须选中状态,即必定安装状态

    原文:Installshield设置feature为必须选中状态,即必定安装状态 上一篇: 解决卸载时残留目标文件夹的问题Installation Designer --> Organizati ...

  8. 分区表在安装系统(MBR)丢失或损坏

    操作系统能识别出硬盘中的各个不同的分区,是靠硬盘分区表(MBR)来识别的. 硬盘分区表中记录了各个分区的位置和大小以及类型等信息,假设这个分区表破坏了,那么这块硬盘里面的分区就会丢失.系统是无法在浏览 ...

  9. 初探Django Admin(一)

    前面的文章记录了django项目的一些操作,插入数据部分是手动在shell中操作的,如果能有一个图形界面来管理我们的数据,那该多好~ Django已经想到大家会需要这个功能,通过简单的配置,就能使用d ...

  10. UC编程:字符读取与行读取

    字符读取函数的应用 下面的演示程序实现从/etc/passwd文件中提取用户名,打印到屏幕上并保存在copyname.txt文件中 使用的函数是getc().putc().putchar() [c] ...