1. 背景

if/else是高级编程语言中最基础的功能,虽然 if/else 是必须的,但滥用 if/else,特别是各种大量的if/else嵌套,会对代码的可读性、可维护性造成很大伤害,对于阅读代码的人来说就是一场灾难。

本系列博客的目的不是消除if/else,而是如何“写好”if/else

2. 方法

根据if/else的使用方式和场景,大概有如下解决方法

多态

表驱动

职责链模式

卫语句

Optional

调整判断逻辑,抽取方法,逻辑优化

本篇博客我介绍的是表驱动,后续博客会介绍其他案例

首先来看下最简单的if…else if…场景,也是经常可以在代码中看到的案例

3. 案例

有如下业务代码demo,根据type值,判断然后返回设备的名称

//逻辑表达模式固定的 if…else
public String getDeviceName(int type){
if (type == 1) {
return "ONT";
} else if (type == 2) {
return "OLT";
} else if (type == 3) {
return "ONU";
} else if (type == 4) {
return "MXU";
}
return null;
}

随着时间的积累和项目的迭代,可能会增加越来越多的类型,那么后人会继续增加if/else分支,代码中存在的分支判断就会越来越多,当分支数量实在是多的难以维护的时候,我们就要考虑下,有办法能让这些代码变得更优雅吗?

可能有的人会说用switch/case来重构代码

public String getDeviceName(int type) {
switch (type) {
case 1:
return "ONT";
case 2:
return "OLT";
case 3:
return "ONU";
case 4:
return "MXU";
default:
return null;
}
}

可以看到,换成switch/case也是一样,后续也要维护大量case分支,特别是当同样的逻辑判断出现在多个地方的时候,代码的可读性和维护难易程度将变得非常的糟糕。每次修改时,你必须找到所有有逻辑分支的地方,并修改它们

下面,我就来介绍一种针对这种if/else判断的最简单的重构方式,那就是使用表驱动

4. 表驱动重构代码

表驱动方法(Table-Driven Methods),《代码大全》对此进行了详细地讲解。

表驱动法是一种编程模式(Scheme),从表里面查找信息而不使用逻辑语句(if 和case) 它的好处是消除代码里面到处出现的if、else、switch语句,让凌乱代码变得简明和清晰。

对简单情况而言,表驱动方法可能仅仅使逻辑语句更容易和直白,但随着逻辑的越来越复杂,表驱动法就愈发有吸引力。

static Map<Integer, String> deviceType2NameMap = new HashMap<>();
static {
deviceType2NameMap.put(1, "ONT");
deviceType2NameMap.put(2, "OLT");
deviceType2NameMap.put(3, "ONU");
deviceType2NameMap.put(4, "MXU");
}

static方式可以在类初始化时就加载,当然,如果不想写成static,也可以自行加载

那么,查询的时候,直接get就可以了,而且不需要对key值进行额外的判空

String deviceName = deviceType2NameMap.get(type);

当然,还有一种逻辑固定的if/else也很常见

if ("run".equals(action)) {
doRun(param);
} else if ("fly".equals(action)) {
doFly(param);
} else if ("sleep".equals(action)) {
doSleep(param);
} // ....

这里分支后的执行过程换成了函数,不同的行为执行不同的函数

转换为表驱动方式如下

public class Test {

// 假定上述的param类型为int
Map<String, Consumer<Integer>> actionMappings = new HashMap<>();
initActionMap(){
// 使用方法引用替换Lambda表达式
// Test::doRun等价于param -> doRun(param)
actionMappings.put("run", Test::doRun);
actionMappings.put("fly", Test::doFly);
actionMappings.put("sleep", Test::doSleep);
} doRun(int param) {...}
doFly(int param) {...}
doSleep(int param) {...}
// ....
}

调用方式如下

actionMappings.get("run").accept(param);

可能有人不清楚Consumer是个什么,为什么最后又执行了accept方法

这里简单说下

Consumer<T>是Java8以后提供的函数式接口

T:入参类型;没有出参

调用方法:void accept(T t);

因为没有出参,常用于打印、发送短信等消费动作

由此可见,表驱动的优势

数据逻辑分离,保证在修改数据时,不会对逻辑产生影响。

单元测试时可以注入表格,只要数据可以转换成表,我们可以输入任意形式的数据。

逻辑固定写死在程序中,因为修改逻辑成本高,数据则是灵活变换的,因为修改数据成本低。

保证多人开发时代码的稳健性,简单的逻辑易于读懂易于维护,并且多人使用时,只用修改数据段即可,而数据本身不需要再测试。

来源:华为云社区征文 作者:EmindCC

#华为云·寻找黑马程序员#【代码重构之路】如何“消除”if/else的更多相关文章

  1. #华为云·寻找黑马程序员#【代码重构之路】使用Pattern的正确姿势

    1.问题 在浏览项目时,发现一段使用正则表达式的代码 这段代码,在循环里执行了Pattern.matches()方法进行正则匹配判断. 查看matches方法的源码,可以看到 每调用一次matches ...

  2. 大型情感剧集Selenium:1_介绍 #华为云·寻找黑马程序员#

    学习selenium能做什么? 很多书籍.文章中是这么定义selenium的: Selenium 是开源的自动化测试工具,它主要是用于Web 应用程序的自动化测试,不只局限于此,同时支持所有基于web ...

  3. python让你再也不为文章配图与素材发愁,让高清图片占满你的硬盘! #华为云·寻找黑马程序员#

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  4. #华为云·寻找黑马程序员# 如何实现一个优雅的Python的Json序列化库

    在Python的世界里,将一个对象以json格式进行序列化或反序列化一直是一个问题.Python标准库里面提供了json序列化的工具,我们可以简单的用json.dumps来将一个对象序列化.但是这种序 ...

  5. 使用Python开发小说下载器,不再为下载小说而发愁 #华为云·寻找黑马程序员#

    需求分析 免费的小说网比较多,我看的比较多的是笔趣阁.这个网站基本收费的章节刚更新,它就能同步更新,简直不要太叼.既然要批量下载小说,肯定要分析这个网站了- 在搜索栏输入地址后,发送post请求获取数 ...

  6. 爬虫新宠requests_html 带你甄别2019虚假大学 #华为云·寻找黑马程序员#

    python模块学习建议 学习python模块,给大家个我自己不专业的建议: 养成习惯,遇到一个模块,先去github上看看开发者们关于它的说明,而不是直接百度看别人写了什么东西.也许后者可以让你很快 ...

  7. #华为云·寻找黑马程序员#微服务-你真的懂 Yaml 吗?

    在Java 的世界里,配置的事情都交给了 Properties,要追溯起来这个模块还是从古老的JDK1.0 就开始了的. "天哪,这可是20年前的东西了,我居然还在用 Properties. ...

  8. 三伏天里小试牛刀andriod 开发 #华为云·寻找黑马程序员#

    2019年07月,北京,三伏天,好热啊.越热自己还越懒得动换(肉身给的信号),但是做为产品经理/交互设计师的,总想着思考些什么(灵魂上给的信号),或者是学习些什么,更有利于将来的职业发展吧,哈哈哈.工 ...

  9. 使用jieba分析小说太古神王中,男主更爱谁?去文章中找答案吧!#华为云·寻找黑马程序员#

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

随机推荐

  1. 【java基础】程序员你真的理解反射机制吗?

    目录 前言 1.反射的概述 2.正式使用反射之前很有必要了解的Class类 3.反射的使用 前言 很多讲解反射的博客文章并没有详细讲解Class类,~当然包括之前的我也一样~,这样的文章只会让反射徒有 ...

  2. 零基础Linux入门之《Linux就该这么学》

    本书是由全国多名红帽架构师(RHCA)基于最新Linux系统共同编写的高质量Linux技术自学教程,极其适合用于Linux技术入门教程或讲课辅助教材,目前是国内最值得去读的Linux教材,也是最有价值 ...

  3. 『题解』Codeforces121A Lucky Sum

    更好的阅读体验 Portal Portal1: Codeforces Portal2: Luogu Description Petya loves lucky numbers. Everybody k ...

  4. [转载]2.5 UiPath循环活动Do While的介绍和使用

    一.Do While的介绍 先执行循环体, 再判断条件是否满足, 如果满足, 则再次执行循环体, 直到判断条件不满足, 则跳出循环. 二.Do While在UiPath中的使用 1. 打开设计器,在设 ...

  5. Linux 项目 shell 自动获取报告本机IP (1) | 通过shell 自动获取报告本机IP

    由于电脑设置静态IP经常出现链接不上网络,动态IP又非常不方便,故有了这个想法并实现 原理: Linux,包含PC机器,树莓派等,通过shell 自动获取报告本机IP  | 通过 Mutt+Msmtp ...

  6. React第一次渲染为何容易出现TypeError: Cannot read property 'XX' of undefined

    此题可能大家会不屑一顾,哎,错误都给你怼脸上了你还不会嘛,其实大家有没有认真思考过这其中的原因.先上一张错误图,剩余的全靠编.没兴趣看图的老铁们可以拉到最底下直接看结论 错误:  代码: 其次,我再把 ...

  7. 如何提高web应用的吞吐量

    这篇博文所列举的优化手段是针对比较传统项目,但是想提高系统的吞吐量现在时髦的技术还是那些前后端未分离, 使用nginx当成静态资源服务器去代理我们的静态资源 是谁限制了Throughput? 当我们对 ...

  8. AI的真实感

    目录 1.让AI"不完美"--估算和假设 2 AI感知 全能感知 特定感觉无知 3 AI的个性 4 AI的预判 5 AI的智能等级 ​ AI的真实感一直是游戏AI程序员追求的目标, ...

  9. MyBatis直接执行sql语句mapper

    <select id="queryBySql" resultType="HashMap"> <![CDATA[ ${sql} ]]> & ...

  10. 人人都懂区块链--pdf电子版学习资料下载

    人人都懂区块链 21天从区块链“小白”到资深玩家电子版pdf下载 链接:https://pan.baidu.com/s/1TWxYv4TLa2UtTgU-HqLECQ 提取码:6gy0 好的学习资料需 ...