过多if-else分支的优化
![]()
http://www.udpwork.com/item/9294.html
我想谈一谈这个话题是因为我的上一篇博客在ITEye上有一些朋友回复,说if-else过多的分支可以使用switch或者责任链模式等等方式来优化。确实,这是一个小问题,不过我们还是可以整理一下这个小问题的重构方式。
为什么要优化?
你没有看错。这是要放在第一条谈论的。
有许多人会说,叠起来一堆if-else分支,代码就不优雅了。可是,怎样去定义“优雅”的概念呢?再退一步说,即便不“优雅”,又有什么问题?
对于这样一段再普通不过的代码:
int code;
if("Name".equals(str))
code = ;
else if("Age".equals(str))
code = ;
else if("Address".equals(str))
code = ;
//...
可以有好多种重构方式,但是使用这样的代码,虽然简陋,但在大多数情况下,并不会影响什么,比如,对可维护性没有影响。当然,如果你发现其中确有不好的一面,那就要考虑重构它。换言之,通常你首先要说出某段代码的问题(比如,你觉得这段代码不符合开闭原则,因为你希望保持这段代码闭合稳定),那么才去存在重构的必要,而不要总是使用“优雅”和“简洁”搪塞疑问。几乎所有的书上都说要写出优雅的、简洁的代码,这本身无可厚非,但是事物需要使用自己的判断,可不要被习惯性地洗了脑。
在我前一家公司,是典型的通讯和传统软件的公司,代码质量普遍不错,但是很多时候,会看到许许多多不够优雅的代码——也许你觉得不够简洁、美观,但是下代码严谨、清晰,我觉得这就很好。反之,某一些精巧的设计,可能会带来可阅读性和可理解性下降的问题。
寻找代替分支判断的方式
接下去我们再来考虑怎么样去重构优化过多的if-else分支。
程序逻辑最基本的组成就是分支、判断和循环。而过多if-else正是由于在某一个变化的点上,有许多判断条件和结果分支造成的。所以最基本的解决办法就是把多个判断条件合成一个,也就是把若干个分支合成一个。
但是在大多数情况下,条件判断的分支都是无法合并的。所以,我们需要把这个变化点通过别的途径封装起来,而不是采用if-else。
1. 用一个Map可以做到,if-else的变化点使用Map的get方法来代替:
Map typeCodeMap = new HashMap();
typeCodeMap.put("Name", );
typeCodeMap.put("Age", );
typeCodeMap.put("Address", );
...
int code = typeCode.get(type);
2. 枚举:
public enum Codes {
Name(), Age(), Address();
public int code;
Codes(int code){
this.code = code;
}
}
//使用:
int code = Codes.valueOf(str).code;
3. 多态:
ICode iCode = (ICode)Class.forName("com.xxx." + str).newInstance();
int code = iCode.getCode();
当然,如果仅考虑从String转向int这样的转换,用这样的方式来简化分支判断逻辑,这个方式、这个例子不是很恰当。当然,这样的方式经常被用来做从字符串到具体对象的转换。
还有一些朋友说的这个模式那个模式来解决多if-else的问题,这些都是正确的,当然本质上也无一例外基于多态来实现的,所以我就不提及了。这些都不错,至少比那些老说用switch来代替if-else的有价值多了 :)
最后,对于如此小的一个问题,我要补充说明的一点是,看不得大片if-else和看不得大片new关键字一样,我觉得这是许多Java程序员的既有观念或者说习惯,甚至通病——这并不好。Java最有价值的地方不是它的语义语法也不是它的虚拟机跨平台和有多高性能,而在于它的社区它的无比丰富的类库,在于使用它的人可以从设计上和宏观上去思考问题。但是Java程序员,也包括我在内,很容易把这条路走得过于极端,比如遍地的Factory,比如漫山遍野的配置,比如永远也不会被复用的可复用代码,比如永远也不会被扩展的可扩展代码,还比如从前到后由内到外的分层,一层又一层。相对于这些方面无止境的追求,我们还是专注于要解决的问题,多写一些清晰可用的代码吧。
过多if-else分支的优化的更多相关文章
- GCC的分支预测优化__builtin_expect
智能指针笔记 GCC的原子操作函数 将流水线引入cpu,可以提高cpu的效率.更简单的说,让cpu可以预先取出下一条指令,可以提供cpu的效率.如下图所示: 取指令 执行指令 输出结果 取指令 执行 ...
- [开发笔记]GCC 分支预测优化
#define likely(x) __builtin_expect(!!(x),1)#define unlikely(x) __builtin_expect(!!(x),0) 用于优化在做分支判断的 ...
- __builtin_expect — 分支预测优化
1.引言 在很多源码如Linux内核.Glib等,我们都能看到likely()和unlikely()这两个宏,通常这两个宏定义是下面这样的形式. #define likely(x) __builtin ...
- mybatis中foreach参数过多效率很慢的优化
foreach 后面in 传入的参数有1万条,#和$是有效率区别的,$的效率远高于#,上篇文章做了比较. 但没达到我的理想结果. 1. 更改方式,把foreach 去掉,改成拼装方式, 参数直接拼装成 ...
- if-else优化
过多if-else分支的优化 超过3个就应该去优化,说if-else过多的分支可以使用switch或者责任链模式等等方式来优化.确实,这是一个小问题,不过我们还是可以整理一下这个小问题的重构方式. ...
- ym——优化你的Java代码(新)
转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 1.面向对象的3要素. 2.面向对象开发的6大原则. 1.单一职责原则 应该有且仅有一 ...
- 【转】MySQL性能优化的最佳21条经验
文章转自: http://blog.csdn.net/waferleo/article/details/7179009 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...
- MYSQL性能优化的最佳20+条经验
MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论 131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...
- MySQL 性能优化的最佳20多条经验分享
当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这 ...
随机推荐
- Linux内存寻址之分段机制
前言 最近在学习Linux内核,读到<深入理解Linux内核>的内存寻址一章.原本以为自己对分段分页机制已经理解了,结果发现其实是一知半解.于是,查找了很多资料,最终理顺了内存寻址的知识. ...
- poj1222
貌似又是一个矩阵图形的问题,看起来应该是不太容易,不管了先做做吧! 题目大意: 题目:灯光延伸出去(延长熄灯)?? 在一个扩展的游戏版本 熄灯,它是一个难题(或者谜)在一个5行每一行有6个按钮(实际是 ...
- C#与java中的集合区别
集合一般的操作 插入: add 删除: remove 查找: contains,remove java中的集合 注意哪些是接口,哪些是实现类 使用集合的时候 1. ...
- tomcat中debug启动和start启动的区别
debug启动tomcat:修改代码不加方法,不加参数,只是单纯的修改方法,不用重启tomcat(热部署). start启动tamcat:修改代码需要重启tomcat.
- angularJS promise $q
Promise 一 介绍 1.什么是promise 我们知道JavaScript语言的执行环境是“单线程”,所谓单线程,就是一次只能够执行一个任务,如果有多个任务的话就要排队,前面一个任务完成后才可以 ...
- 《Java 并发编程实战》读书笔记之二:图文讲述同步的另一个重要功能:内存可见性
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17288243 加锁(synchronized同步)的功能不仅仅局限于互斥行为,同时还存在另 ...
- Failed dependencies: 检查依赖性错误 解决方法
centOs下: error: Failed dependencies: 检查依赖性错误 解决方法 刚才安装avast的linux版,结果出现了: [root@localhost /]# rpm -i ...
- stl_alloc.h
/* * Copyright (c) 1996-1997 * Silicon Graphics Computer Systems, Inc. * * Permission to use, copy, ...
- 解决ASP.NET中ReportView与IE11的兼容性问题
前久发现以前用ReportView开发的一个软件的报表,在IE11上运行时出错,陆续查了好几天才解决了问题. 开发环境: VS2010,ReportView 10.0.402,RDLC报表模板 问题: ...
- LINUX 内核代码 errno 错误代码提示 /include/asm/errno.h
首先在自己的程序中#include<errno.h> 添加打印errno的语句 printf("errno is: %d\n",errno); 根据errno的值查错. ...