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分支的优化的更多相关文章

  1. GCC的分支预测优化__builtin_expect

    智能指针笔记 GCC的原子操作函数 将流水线引入cpu,可以提高cpu的效率.更简单的说,让cpu可以预先取出下一条指令,可以提供cpu的效率.如下图所示: 取指令 执行指令 输出结果 取指令 执行 ...

  2. [开发笔记]GCC 分支预测优化

    #define likely(x) __builtin_expect(!!(x),1)#define unlikely(x) __builtin_expect(!!(x),0) 用于优化在做分支判断的 ...

  3. __builtin_expect — 分支预测优化

    1.引言 在很多源码如Linux内核.Glib等,我们都能看到likely()和unlikely()这两个宏,通常这两个宏定义是下面这样的形式. #define likely(x) __builtin ...

  4. mybatis中foreach参数过多效率很慢的优化

    foreach 后面in 传入的参数有1万条,#和$是有效率区别的,$的效率远高于#,上篇文章做了比较. 但没达到我的理想结果. 1. 更改方式,把foreach 去掉,改成拼装方式, 参数直接拼装成 ...

  5. if-else优化

    过多if-else分支的优化   超过3个就应该去优化,说if-else过多的分支可以使用switch或者责任链模式等等方式来优化.确实,这是一个小问题,不过我们还是可以整理一下这个小问题的重构方式. ...

  6. ym——优化你的Java代码(新)

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 1.面向对象的3要素. 2.面向对象开发的6大原则. 1.单一职责原则 应该有且仅有一 ...

  7. 【转】MySQL性能优化的最佳21条经验

    文章转自: http://blog.csdn.net/waferleo/article/details/7179009 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...

  8. MYSQL性能优化的最佳20+条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  9. MySQL 性能优化的最佳20多条经验分享

    当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这 ...

随机推荐

  1. [置顶] 【Git入门之十五】Github操作指南

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12374633 最终篇,介绍一下Github网站的使用,主要是翻译为主,简化了 ...

  2. kafka单机安装配置

    1.下载kafka wget https://www.apache.org/dyn/closer.cgi?path=/kafka/0.8.2.1/kafka_2.9.2-0.8.2.1.tgz 2.解 ...

  3. Linux用户与用户组的详解

    1,用户和用户组文件   在linux中,用户帐号,用户密码,用户组信息和用户组密码均是存放在不同的配置文件中的.   在linux系统中,所创建的用户帐号和其相关信息(密码除外)均是存放在/etc/ ...

  4. msyql 字节问题

    MySQL 数据库的varchar类型在4.1以下的版本中的最大长度限制为255,其数据范围可以是0~255或1~255(根据不同版本数据库来定).在 MySQL5.0以上的版本中,varchar数据 ...

  5. 用htaccess进行访问控制(转)

    1. 文件访问控制 利用 httpd.conf 中的 Order.Files 及 FilesMatch 命令实现的访问控制可以满足大部分要求,但是当用户被拒绝时,他们看到的是硕大的“403 Forbi ...

  6. Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  7. SPOJ 345 - Mixtures 区间动态规划

    有n个混合物排成一排,每个混合物有一个颜色值0<=color<=99, 规定合并只能合并相邻两个, 将颜色a的混合物与颜色b的混合物合并后,颜色为( a+b ) % 100,并产生a*b的 ...

  8. python小练习,打出1-100之间的所有偶数,设计一个函数,在桌面上创建10个文件,并以数字命名,复利计算函数

    练习一:打出1-100之间的所有偶数 def even_print(): for i in range(1,101): if i % 2 == 0: print (i) even_print() #列 ...

  9. Activity 【生命周期】

    不同情况下的回调 我们打开应用时先后调用了onCreate()->onStart()->onResume 当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause( ...

  10. jQuery的矿建结构小demo举例

    (function (global) { var document = global.document,//变成局部变量提高搜索的性能 init;// 核心函数 function itcast(sel ...