我想谈一谈这个话题是因为我的上一篇博客有一些朋友回复说ifelse过多的分支可以使用switch或者责任链模式等等方式来优化确实这是一个小问题不过我们还是可以整理一下这个小问题的重构方式 为什么要优化? 你没有看错这是要放在第一条谈论的 有许多人会说叠起来一堆ifelse分支代码就不优雅了可是怎样去定义优雅的概念呢?再退一步说即便不优雅又有什么问题? 对于这样一段再普通不过的代码 int code; if(Nameequals(str)) code = ; else if(Ageequals(str)) code = ; else if(Addressequals(str)) code = ;
可以有好多种重构方式但是使用这样的代码虽然简陋但在大多数情况下并不会影响什么比如对可维护性没有影响当然如果你发现其中确有不好的一面那就要考虑重构它换言之通常你首先要说出某段代码的问题(比如你觉得这段代码不符合开闭原则因为你希望保持这段代码闭合稳定)那么才去存在重构的必要而不要总是使用优雅和简洁搪塞疑问几乎所有的书上都说要写出优雅的简洁的代码这本身无可厚非但是事物需要使用自己的判断可不要被习惯性地洗了脑 在我前一家公司是典型的通讯和传统软件的公司代码质量普遍不错但是很多时候会看到许许多多不够优雅的代码——也许你觉得不够简洁美观但是下代码严谨清晰我觉得这就很好反之某一些精巧的设计可能会带来可阅读性和可理解性下降的问题 寻找代替分支判断的方式 接下去我们再来考虑怎么样去重构优化过多的ifelse分支 程序逻辑最基本的组成就是分支判断和循环而过多ifelse正是由于在某一个变化的点上有许多判断条件和结果分支造成的所以最基本的解决办法就是把多个判断条件合成一个也就是把若干个分支合成一个 但是在大多数情况下条件判断的分支都是无法合并的所以我们需要把这个变化点通过别的途径封装起来而不是采用ifelse 用一个Map可以做到ifelse的变化点使用Map的get方法来代替 Map typeCodeMap = new HashMap(); typeCodeMapput(Name ); typeCodeMapput(Age ); typeCodeMapput(Address );
int code = typeCodeget(type); 枚举 public enum Codes { Name() Age() Address(); public int code; Codes(int code){ de = code; } } //使用 int code = CodesvalueOf(de; 多态 ICode iCode = (ICode)ClassforName(comxxx + str)newInstance(); int code = iCodegetCode(); 当然如果仅考虑从String转向int这样的转换用这样的方式来简化分支判断逻辑这个方式这个例子不是很恰当当然这样的方式经常被用来做从字符串到具体对象的转换 还有一些朋友说的这个模式那个模式来解决多ifelse的问题这些都是正确的当然本质上也无一例外基于多态来实现的所以我就不提及了这些都不错至少比那些老说用switch来代替ifelse的有价值多了 :) 最后对于如此小的一个问题我要补充说明的一点是看不得大片ifelse和看不得大片new关键字一样我觉得这是许多Java程序员的既有观念或者说习惯甚至通病——这并不好Java最有价值的地方不是它的语义语法也不是它的虚拟机跨平台和有多高性能而在于它的社区它的无比丰富的类库在于使用它的人可以从设计上和宏观上去思考问题但是Java程序员也包括我在内很容易把这条路走得过于极端比如遍地的Factory比如漫山遍野的配置比如永远也不会被复用的可复用代码比如永远也不会被扩展的可扩展代码还比如从前到后由内到外的分层一层又一层相对于这些方面无止境的追求我们还是专注于要解决的问题多写一些清晰可用的代码吧 |