消除Switch...Case的过程
http://www.cnblogs.com/happyframework/p/3300170.html
目录
备注返回目录
不要重复自己,也不要重复别人,一旦养成了“拷贝和粘贴”的习惯,写程序的时候非常容易导致重复,好在一直暗示自己要稍后进行重构,本文给出一个重构的示例。
需求返回目录
需求:按照年、月和日显示销售数据,根据不同的周期类型,有三个问题需要注意:
- 默认的日期范围不同
- 图表中显示的格式不同
- 默认的模拟数据不同(发布环境会使用真实的数据)
如下图:

第一遍代码(重复的代码)返回目录
最爱的拷贝和粘贴。
默认的日期范围不同

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的过程的更多相关文章
- 设计原则:消除Switch...Case的过程,可能有点过度设计了。
备注 不要重复自己,也不要重复别人,一旦养成了“拷贝和粘贴”的习惯,写程序的时候非常容易导致重复,好在一直暗示自己要稍后进行重构,本文给出一个重构的示例. 需求 需求:按照年.月和日显示销售数据,根据 ...
- Java代码消除switch/case,if/else语句的几种实现方式
转自:https://my.oschina.net/stefanzhlg/blog/372413 我们在平时的编码中,我们经常会遇到这样的情况: 使用过多的switch/case 或者 if else ...
- switch case 与 if
case 在编程中偶尔使用到switch case语句,对于case语句的处理,出现了两种错误,现总结如下: case后必须是常量.布尔类型.字符(不能是字符串): case后如果是‘||’或者‘&a ...
- 为什么switch...case语句比if...else执行效率高
在C语言中,教科书告诉我们switch...case...语句比if...else if...else执行效率要高,但这到底是为什么呢?本文尝试从汇编的角度予以分析并揭晓其中的奥秘. 第一步,写一个d ...
- 使用反射+策略模式代替项目中大量的switch case判断
我这里的业务场景是根据消息类型将离线消息存入mongoDB不同的collection中.其中就涉及到大量的分支判断,为了增强代码的可读性和可维护性,对之前的代码进行了重构. 先对比一下使用反射+策略模 ...
- 知识扩展--if...else...与switch...case...的执行原理
一.简述 编程语言中的条件分支结构有两种:if-else和switch-case,这两种条件分支之间可以相互转换,但是也存在一些区别,那么什么时候该用if-else,什么时候该用switch-case ...
- 浅析C/C++中的switch/case陷阱
浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp #include<iostream> using namespace std; int main(i ...
- Java基础之循环语句、条件语句、switch case 语句
Java 循环结构 - for, while 及 do...while 顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构. Java中有三种主要的循环结构: whi ...
- python中Switch/Case实现
学习Python过程中,发现没有switch-case,过去写C习惯用Switch/Case语句,官方文档说通过if-elif实现.所以不妨自己来实现Switch/Case功能. 方法一 通过字典实现 ...
随机推荐
- C# Email邮件发送,功能是密码找回或者重置功能。
原文:C# Email邮件发送,功能是密码找回或者重置功能. 最近根据公司需求,写个邮件发送. 这里面的传入的地址信息的参数都是经过加密的. 主要是保证用户信息的安全. 帮助类 using ...
- 私人定制javascript事件处理机制(浅谈)
看到园子里关于事件监听发表的文章,我都有点不好意思写了.不过想想我的题目以私人定制作开头也就妥妥地写吧. 事件相关概念 1.事件类型 发生事件的字符串 有传统事件类型 比如表单.window事件等 D ...
- 【百度地图API】批量地址解析与批量反地址解析(带商圈数据)
原文:[百度地图API]批量地址解析与批量反地址解析(带商圈数据) 摘要:因为地址解析的webserives方式还没有开通,所以先用JS版本的地址解析接口来批量获取地址解析数据吧,同时还能得到商圈的数 ...
- Spark Standalone模式应用程序开发
作者:过往记忆 | 新浪微博:左手牵右手TEL | 能够转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明博客地址:http://www.iteblog.com/文章标题:<Spar ...
- 在ASP.NET应用中执行后台任务
在ASP.NET应用中执行后台任务 昨天下午,在微软的MVP 2015社区大讲堂上给大家分享了一个题目:在ASP.NET应用中执行后台任务.这是一点都不高大上,并且还有点土气的技术分享.不过我相信很多 ...
- 文字超出DIV后,隐藏文字并显示...
<html> <head> <style type="text/css"> #cs{width:100px;height:50px;line-h ...
- 最新发布树莓派2代Wi-Fi自动连接实战(适合初学者)
话说天地会珠海分舵在上几天才刚给大家分享了个海外资讯说树莓派2已经发布且Windows10加盟之类的资讯,具体请查看<海外优秀资讯抢先看8 - Windows 10 for Raspberry ...
- Python 2.7 Exception格式化工具
首先说一个发现: try: 抛错误,抛异常 except Exception as e: 都被这里抓住了 except Error as e: 这里啥事都没了 然后,说说Exception as e的 ...
- Android高效的应用程序开发工具集1---ant构建一个简单的Android工程
在java编译那些事通过提到ant编译Java工程,如今扩大到用它来构建Android目,事实上道理是相通的.变化的仅仅是使用的形式.ant构建相比IDE的优点是多个子项目使用自己定义jar包时,an ...
- java查找反复类/jar包/普通文件
开发web应用时,有时更新了类却没有生效,事实上是由于jboss/tomcat中其它公布包下有同名类(包含全路径都同样). 于是萌发了做个程序来检查指定文件夹是否存在反复类(通过asm从类文件里取类的 ...