#华为云·寻找黑马程序员#【代码重构之路】如何“消除”if/else
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的更多相关文章
- #华为云·寻找黑马程序员#【代码重构之路】使用Pattern的正确姿势
1.问题 在浏览项目时,发现一段使用正则表达式的代码 这段代码,在循环里执行了Pattern.matches()方法进行正则匹配判断. 查看matches方法的源码,可以看到 每调用一次matches ...
- 大型情感剧集Selenium:1_介绍 #华为云·寻找黑马程序员#
学习selenium能做什么? 很多书籍.文章中是这么定义selenium的: Selenium 是开源的自动化测试工具,它主要是用于Web 应用程序的自动化测试,不只局限于此,同时支持所有基于web ...
- python让你再也不为文章配图与素材发愁,让高清图片占满你的硬盘! #华为云·寻找黑马程序员#
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- #华为云·寻找黑马程序员# 如何实现一个优雅的Python的Json序列化库
在Python的世界里,将一个对象以json格式进行序列化或反序列化一直是一个问题.Python标准库里面提供了json序列化的工具,我们可以简单的用json.dumps来将一个对象序列化.但是这种序 ...
- 使用Python开发小说下载器,不再为下载小说而发愁 #华为云·寻找黑马程序员#
需求分析 免费的小说网比较多,我看的比较多的是笔趣阁.这个网站基本收费的章节刚更新,它就能同步更新,简直不要太叼.既然要批量下载小说,肯定要分析这个网站了- 在搜索栏输入地址后,发送post请求获取数 ...
- 爬虫新宠requests_html 带你甄别2019虚假大学 #华为云·寻找黑马程序员#
python模块学习建议 学习python模块,给大家个我自己不专业的建议: 养成习惯,遇到一个模块,先去github上看看开发者们关于它的说明,而不是直接百度看别人写了什么东西.也许后者可以让你很快 ...
- #华为云·寻找黑马程序员#微服务-你真的懂 Yaml 吗?
在Java 的世界里,配置的事情都交给了 Properties,要追溯起来这个模块还是从古老的JDK1.0 就开始了的. "天哪,这可是20年前的东西了,我居然还在用 Properties. ...
- 三伏天里小试牛刀andriod 开发 #华为云·寻找黑马程序员#
2019年07月,北京,三伏天,好热啊.越热自己还越懒得动换(肉身给的信号),但是做为产品经理/交互设计师的,总想着思考些什么(灵魂上给的信号),或者是学习些什么,更有利于将来的职业发展吧,哈哈哈.工 ...
- 使用jieba分析小说太古神王中,男主更爱谁?去文章中找答案吧!#华为云·寻找黑马程序员#
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
随机推荐
- 网络安全-主动信息收集篇第二章-二层网络扫描之scapy
scapy是python第三方库文件,可以使用python进行调用也单独进行使用. 非常强大可以用于抓包.分析.创建.修改.注入网络流量. 使用scapy 详细使用方式可以查看github:https ...
- NOIP模拟 10
(果然题目描述越人畜无害,题目难度越丧心病狂) (感觉T2大大锻炼了我的码力) T1 辣鸡 看见自己作为题目标题出现在模拟赛中,我内心无比激动 看完题面,一个N^2暴力思路已经成形 然后开始拼命想正解 ...
- Java中打印日志,这4点很重要!
目录 一.预先判断日志级别 二.避免无效日志打印 三.区别对待错误日志 四.保证记录完整内容 打印日志,要注意下面4点. 一.预先判断日志级别 对DEBUG.INFO级别的日志,必须使用条件输出或者使 ...
- P3097 [USACO13DEC]最优挤奶(线段树优化dp)
盲猜dp系列... 题意:给定序列,选了i就不能选与i相邻的两个,求最大值,带修改 蒟蒻在考场上10min打完以为只有两种情况的错解...居然能骗一点分... 先讲下当时的思路吧. f[i][0/1] ...
- Java Part 001( 01_01_Java概述 )
Java作为编程语言, 甚至超出了语言的范畴, 成为一种开发平台, 一种开发规范. Java语言相关的JavaEE规范里, 包含了时下最流行的各种软件工程理念, 学习Java相当于系统的学习了软件开发 ...
- python——函数的基本概念
Python函数认识 数学定义 y = f(x), y是x的函数,x是自变量. python中的函数组成 由若干语句组成的语句块.函数名称.参数列表构成,函数是组织代码的最小单元 像一个黑盒子,我们给 ...
- C语言I博客作业08
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 作业 我在这个课程的目标是 熟悉使用while和do-while结构解决问题 这个作业在那个具体方面帮助我实现目标 pta题目及查找的资料 ...
- 使用火狐浏览器模仿手机浏览器,附浏览器HTTP_USER_AGENT汇总
HTTP_USER_AGENT用来获取浏览页面的访问者在用什么操作系统(包括版本号)浏览器(包括版本号)和用户个人偏好. 改变浏览器的这个参数就可以伪装成相应的浏览器. User Agent Swit ...
- 手把手教你实现热更新功能,带你了解 Arthas 热更新背后的原理
文章来源:https://studyidea.cn/java-hotswap 一.前言 一天下午正在摸鱼的时候,测试小姐姐走了过来求助,说是需要改动测试环境 mock 应用.但是这个应用一时半会又找不 ...
- R画图——分屏
最近项目需求,用R画了一个九宫格的图,第一次画,将简化后的脚本呈现一下,不是有人说,既然做了,那就摆出来吧. *中文行为说明: args <- commandArgs(T) 调用命令行读取 fi ...