过多if-else分支的优化

 

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

为什么要优化?

你没有看错。这是要放在第一条谈论的。

有许多人会说,叠起来一堆if-else分支,代码就不优雅了。可是,怎样去定义“优雅”的概念呢?再退一步说,即便不“优雅”,又有什么问题?

对于这样一段再普通不过的代码:

1
2
3
4
5
6
7
8
int code;
if("Name".equals(str))
    code = 0;
else if("Age".equals(str))
    code = 1;
else if("Address".equals(str))
    code = 2;
...

可以有好多种重构方式,但是使用这样的代码,虽然简陋,但在大多数情况下,并不会影响什么,比如,对可维护性没有影响。当然,如果你发现其中确有不好的一面,那就要考虑重构它。换言之,通常你首先要说出某段代码的问题(比如,你觉得这段代码不符合开闭原则,因为你希望保持这段代码闭合稳定),那么才去存在重构的必要,而不要总是使用“优雅”和“简洁”搪塞疑问。几乎所有的书上都说要写出优雅的、简洁的代码,这本身无可厚非,但是事物需要使用自己的判断,可不要被习惯性地洗了脑。

在我前一家公司,是典型的通讯和传统软件的公司,代码质量普遍不错,但是很多时候,会看到许许多多不够优雅的代码——也许你觉得不够简洁、美观,但是下代码严谨、清晰,我觉得这就很好。反之,某一些精巧的设计,可能会带来可阅读性和可理解性下降的问题。

寻找代替分支判断的方式

接下去我们再来考虑怎么样去重构优化过多的if-else分支。

程序逻辑最基本的组成就是分支、判断和循环。而过多if-else正是由于在某一个变化的点上,有许多判断条件和结果分支造成的。所以最基本的解决办法就是把多个判断条件合成一个,也就是把若干个分支合成一个。

但是在大多数情况下,条件判断的分支都是无法合并的。所以,我们需要把这个变化点通过别的途径封装起来,而不是采用if-else。

1. 用一个Map可以做到,if-else的变化点使用Map的get方法来代替:

1
2
3
4
5
6
Map typeCodeMap = new HashMap();
typeCodeMap.put("Name", 0);
typeCodeMap.put("Age", 1);
typeCodeMap.put("Address", 2);
...
int code = typeCode.get(type);

2. 枚举:

1
2
3
4
5
6
7
8
9
10
11
public enum Codes {
    Name(0), Age(1), Address(2);
     
    public int code;
    Codes(int code){
        this.code = code;
    }
}
 
//使用:
int code = Codes.valueOf(str).code;

3. 多态:

1
2
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. 关于DOM的操作以及性能优化问题-重绘重排

     写在前面: 大家都知道DOM的操作很昂贵. 然后贵在什么地方呢? 一.访问DOM元素 二.修改DOM引起的重绘重排 一.访问DOM 像书上的比喻:把DOM和JavaScript(这里指ECMScri ...

  2. In-Memory:内存优化表的事务处理

    内存优化表(Memory-Optimized Table,简称MOT)使用乐观策略(optimistic approach)实现事务的并发控制,在读取MOT时,使用多行版本化(Multi-Row ve ...

  3. 试试SQLSERVER2014的内存优化表

    试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...

  4. 01.SQLServer性能优化之----强大的文件组----分盘存储

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 文章内容皆自己的理解,如有不足之处欢迎指正~谢谢 前天有学弟问逆天:“逆天,有没有一种方 ...

  5. 03.SQLServer性能优化之---存储优化系列

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 概  述:http://www.cnblogs.com/dunitian/p/60413 ...

  6. 前端网络、JavaScript优化以及开发小技巧

    一.网络优化 YSlow有23条规则,中文可以参考这里.这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少. 1)合并压缩CSS.JavaScript.图片,静态资源CDN ...

  7. 数据库优化案例——————某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  8. 【前端性能】高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  9. Web性能优化:What? Why? How?

    为什么要提升web性能? Web性能黄金准则:只有10%~20%的最终用户响应时间花在了下载html文档上,其余的80%~90%时间花在了下载页面组件上. web性能对于用户体验有及其重要的影响,根据 ...

  10. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题

    最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerP ...

随机推荐

  1. dubbo属性配置

    一.覆盖策略 JVM启动-D参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口.XML次之,如果在XML中有配置,则dubbo.properties中的相应配置项无效.P ...

  2. jQuery val()方法及valHooks源码解读

    val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) {//无参数 ...

  3. TI德州芯片TLV系列和TPS系列芯片区别(转)

    TLV和TPS一般会有pin to pin的对应型号: 一般来讲,TPS精度.准确度和性能会好一些,所以价钱要贵一些: 对应TLV就是一样可以实现上述功能,但是精度和性能等级是稍微低一点的: 具体选择 ...

  4. 前端之CSS字体和文本类属性

    一.字体类属性: 1.字体类型: font-family:字体1,字体2,字体3; 常用写法: font-family:"微软雅黑",Arial; 注:a) 多个字体之间用逗号分隔 ...

  5. IT兄弟连 JavaWeb教程 Servlet定义以及环境配置 BS程序和CS程序

    随着网络技术的不断发展,单机的软件程序已难以满足网络计算机的需求.为此,各种各样的网络程序开发体系结构应运而生.其中,运用最多的网络应用程序开发体系结构可以分为两种,一种是基于客户端/服务器的C/S结 ...

  6. vue之导入Bootstrap和Jquery

    Vue引入bootstrap主要有两种方法 方法一:在main.js中引入,此方法导入的bootstrap中对于html,body的一些预设置的css样式可能无效. 一.引入jQuery 在当前项目的 ...

  7. 求矩阵的n次方 c语言实现

    矩阵的n次方,比较容易理解的想法是递归. 思路是这样的,把n分成两部分,当n是偶数的时候,即为左右两边的乘积,如果n是奇数,即为左右两边的乘积再乘a ) matrixn())^*a else matr ...

  8. Linux中yum、rpm、configure使用介绍

    安装程序命令介绍 安装包选择策略:能上外网:yum方式.绿色方式->不能上外网:rpm方式.configure方式 1.yum命令yum安装包时,会包所依赖的包也会安装到系统,将源换成163的源 ...

  9. 清理ThreadLocal

    在我很多的课程里(master.concurrency.xj-conc-j8),我经常提起ThreadLocal.它经常受到我严厉的指责要尽可能的避免使用.ThreadLocal是为了那些使用完就销毁 ...

  10. Codeforces Round #316 (Div. 2) D Tree Requests

    官方题解是离线询问,dfs树形转线性,然后二分找区间. 还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案. 代码是学 ...