如何减少代码中的if-else嵌套
实际项目中,往往有大量的if-else语句进行各种逻辑校验,参数校验等等,大量的if-else,语句使代码变得臃肿且不好维护,本篇文章结合我自己的经验,就减少if-else语句给出以下几种方案,分别适用于不同的场景,供大家参考,如有疑问或者建议,请大家及时指出;
一. 方案一:使用三元表达式:
//使用if-else语句
String str;
if (user.getAge()>18){
str="已成年";
}else {
str="未成年";
}
//使用三元表达式
str=user.getAge()>18?"成年":"未成年";
二. 方案二:使用JDK1.8中的Optional类包装
//使用 if 语句
User user=userService.findById(userId);
if (null==user){
throw new RuntimeException("参数错误,未找到指定用户");
}
//使用Optional类包装
Optional.ofNullable(userService.findById(userId)).orElseThrow(()->new
RuntimeException("参数错误,未找到指定用户"));
使用Optional类的好处还在于在包装成Optional容器后,可以使用函数式编程中的相关方法,例如filter(),map()方法,等等,用于筛选和转换我们业务中的逻辑和对象,使得代码得灵活性大大提高,例如:
//筛选出大于18岁的用户,如果没有就抛出异常
Optional.ofNullable(userService.findById(userId))
.filter(x->x.getAge()>18)
.orElseThrow(()->new RuntimeException("参数错误,未找到指定用户"));
代码是否简洁了很多呢
优点: 可以进行较为复杂的逻辑判断
缺点: 条件判断不宜过多,过多的条件判断下不宜使用该方式
三.方案三:使用断言Assert类
在Spring的org.springframework.util包中,内置了Assert断言类,用于条件表达式的判断
//使用断言类
User user=userService.findById(userId);
Assert.notNull(user, "参数错误,未找到指定用户");
断言类中的方法返回值是void,断言类常用于我们做Junit单元测试,由于单元测试的方法均是无参数,无返回值的方法,因此Assert断言类用于测试程序的返回值是否符合我们预期是再好不过了
优点:内置了很多判断方法,例如 notNull,notEmpty,equal等方法,代码可读性强,相对方案一和方案二,可以适用于较多的判断分支;
缺点:在断言失败时,异常只能是IllegalArgumentException(message),适用于较简单的逻辑判断
四.方案四:使用@Validate注解进行入参校验的判断
在企业开发中,进行表单验证,以及接口的入参校验时,往往会使用大量的if-else语句做参数校验,这样代码会显得特别臃肿和冗余,因此我们可以使用封装好的库来进行校验,在JSR-303规范中,定义了参数校验的注解@Valid,个大框架厂商例如spring,基于JSR303规范,提供了各自的实现,并且提供了很多高级的功能,例如@Validated就是@Valid的变体;
以下摘自org.springframework.validation.annotation中@Validated注解的文档注释
Variant of JSR-303's {@link javax.validation.Valid}, supporting the specification of validation groups. Designed for convenient use with Spring's JSR-303 support but not JSR-303 specific.
//接口定义
@RequestMapping("/update")
public void updateUser(@RequestBody @Validated User user) {
userService.updateUser(user);
}
//参数校验
public class User implements Serializable {
@NotNull(message = "参数不能为空")
private Integer id; @NotBlank(message = "参数不能为空")
private String username; @NotBlank(message = "参数不能为空")
private String password; @NotEmpty(message = "参数不能为空")
private List<String> desc; //这里可以通过正则来校验时间格式是否正确
@NotNull(message = "参数不能为空")
@Pattern(regexp = "xxxx",message ="时间格式不符合规范" )
private Date date;
}
注意:如果@Validated参数校验失败,会抛出异常,如果需要在代码中接收异常,可以在接口的参数中,添加参数BindingResult,添加了这个类,之后,异常就会被封装到这个类中,不会向外抛出,我们可以调用这个类的API去获取具体的异常信息,之后,我们可以根据异常信息,去定制化我们自己的响应
public ModelAndView save(@Validated CategoryForm form,
BindingResult bindingResult,
Map<String, Object> map) {
if (bindingResult.hasErrors()) {
map.put("msg", bindingResult.getFieldError().getDefaultMessage());
map.put("url", "/sell/seller/category/index");
return new ModelAndView("common/error", map);
}
}
优点: 非常适合在特定环境下做接口入参的校验
缺点: 局限性大,无法在业务逻辑中使用
五.方案五:策略模式
策略模式是设计模式之一,设计模式的初衷是为了解决代码中的特定问题而存在,百度一下策略模式的定义:
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
简单来说就是,算法(策略)和对象已经预先定义好,随传入参数的改变而选择不同的算法(策略),更加具体的语义不就是根据不用的条件(if--else),选择性的执行不同的代码吗? 本人在开发中也是屡次使用策略模式来重构复杂的if-else逻辑判断,屡试不爽,大大提高代码的优雅性;
下面是在企业开发中本人的例子,在Spring中如何使用策略模式 使用场景: 需求:多个接口,响应相同,根据参数传入的类型,使用不同的策略;
//策略上下文
@Configuration
public class StrategyContext{ @Resource
public Map<String,Strategy> strategyMap; public List<Resp> doGet(String type){
Strategy strategy =strategyMap.get(type);
retun strategy.doStrategy();
}
}
//配置策略
@Configuration
public class StrategyConfig{
@Resource
public ServiceImpl1 serviceImpl1 @Resource
public ServiceImpl2 serviceImpl2 @Bean
public Map<String,Strategy> getMap(){
Map<String,Strategy> strategyMap =new HashMap()
strategyMap.put("1",new ServiceImpl1());
strategyMap.put("2",new ServiceImpl2());
return strategyMap
}
//策略接口类
public interface Strategy{
List<Resp> doStrategy();
}
//具体策略1
public class ServiceImpl1 implements Strategy{
//重写策略方法
@Override
publicList<Resp> doStrategy(){
...
}
}
//具体策略2
public class ServiceImpl2 implements Strategy{
//重写策略方法
@Override
publicList<Resp> doStrategy(){
...
}
}
//在Controller层的代码中注入策略上下文
public class AAAController{
@Autowired
public StrategyContext context; public List<Resp> getXXX(String type){
//设计模式-策略模式
return context.doGet(type)
} }
优点 :适合复杂的业务逻辑,代码可扩展性强
缺点: 通常要配合工厂模式或者享元模式使用
如何减少代码中的if-else嵌套的更多相关文章
- 论减少代码中return语句的骚操作
一.写作背景 最近组内在推行checkstyle代码规范的检测,关于checkstyle的介绍可以参考:https://checkstyle.sourceforge.io, 在按照checkstyle ...
- FindBugs 入门——帮你减少代码中的bug数
FindBugs 入门 FindBugs 作用 开发人员在开发了一部分代码后,可以使用FindBugs进行代码缺陷的检查.提高代码的质量,同时也可以减少测试人员给你报的bug数. 代码缺陷分类 根据缺 ...
- 有效的减少代码中太多的if、else?-策略模式
写这篇文章的目的和上一篇单例模式一样,策略模式也是一种常用的设计模式,太多的if-else不仅看着不太美观而且不好维护,对于自己来说也等于复习了一遍策略模式.先说一下策略 模式的定义: 策略模式封装了 ...
- 如何在代码中减少if else语句的使用
前言 代码中嵌套的if/else结构往往导致代码不美观,也不易于理解.面向过程的开发中代码有大量的if else,在java中可以用一些设计模式替换掉这些逻辑,那么在js中是否也有类似的方法用来尽可能 ...
- 写代码的心得,怎么减少编程中的 bug?
遭遇 bug 的时候,理性的程序员会说:这个 bug 能复现吗? 自负型:这不可能,在我这是好好的. 经验型:不应该,以前怎么没问题? 幻想型:可能是数据有问题. 无辜型:我好几个星期都没碰这块代码了 ...
- Java基础学习总结(81)——如何尽可能的减少Java代码中bug
Java编程语言的人气自然无需质疑,从Web应用到Android应用,这款语言已经被广泛用于开发各类应用及代码中的复杂功能. 不过在编写代码时,bug永远是困扰每一位从业者的头号难题.在今天的文章中, ...
- php中嵌套html代码和html代码中嵌套php方式
php中嵌套html代码和html代码中嵌套php方式 一.总结 拷贝的话直接html代码是极好的方式 1.php中嵌套html代码(本质是原生php):a.原生嵌套<?php .....?&g ...
- 如何解决代码中if…else 过多的问题
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- “System.OutOfMemoryException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理
“System.OutOfMemoryException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理 这个原因肯定不是因为程序内部的逻辑错误,或者别的什么情况. 想想,肯 ...
随机推荐
- Machine Learning:机器学习算法
原文链接:https://riboseyim.github.io/2018/02/10/Machine-Learning-Algorithms/ 摘要 机器学习算法分类:监督学习.半监督学习.无监督学 ...
- SYSAUX表空间满,
step1. 确认到底是哪个段占用了sysaux空间: select segment_name,sum(bytes)/1024/1024 from dba_segments where tables ...
- MyCat(1.2)Mycat的安装
[0]基本环境 OS:CentOS7.5 Software envireonment:JDK1.7.0 Master Software:Mycat1.6.5 Linux Client:CRT 8.0 ...
- YOLOv1到YOLOv3的演变过程及每个算法详解
1,YOLOv1算法的简介 YOLO算法使用深度神经网络进行对象的位置检测以及分类,主要的特点是速度够快,而且准确率也很高,采用直接预测目标对象的边界框的方法,将候选区和对象识别这两个阶段合二为一, ...
- FreeBSD虚拟机——小折腾
最近,突然想起来Linux了,因为前段时间接触了DOS命令,提高了自己的工作效率,这会想再温习下Linux的CLI,无奈windows下unix命令,水土不服,因此想尝试虚拟机,虚拟机软件无非vmwa ...
- sql中使一个字段升序,一个字段降序
ORDER BY _column1, _column2; /* _column1升序,_column2升序 */ ORDER BY _column1, _column2 DESC; /* _colum ...
- jenkins 更改端口
方法一 在Jenkins目录下,运行一下命令: java -jar jenkins.war --ajp13Port=-1 --httpPort=8081 出现了错误: C:\Program Files ...
- webpack.config.js配置入口出口文件
目录结构: 新建webpack.config.js配置文件 const path = require('path') //导出 path是node内置的包 通过npm init初始化得到package ...
- 威胁预警|Solr velocity模板注入远程命令执行已加入watchbog武器库,漏洞修补时间窗口越来越短
概述 近日,阿里云安全团队监测到挖矿团伙watchbog更新了其使用的武器库,增加了最新Solr Velocity 模板注入远程命令执行漏洞的攻击方式,攻击成功后会下载门罗币挖矿程序进行牟利.建议用户 ...
- spring-boot整合shiro实现权限管理
1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...