如何减少代码中的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 中发生,但未在用户代码中进行处理 这个原因肯定不是因为程序内部的逻辑错误,或者别的什么情况. 想想,肯 ...
随机推荐
- 阿里云搭建香港代理服务器 shadownsocks
阿里云香港代理服务器搭建方式: 1.阿里云官网购买轻量级服务器即可,流量,配置套餐自己选择,CENTOS7,进入控制台后打开端口管理列表,打开9000即可. 2.安装shadownsocks服务端: ...
- python常用函数 T
timedelta() timedelta方法可以表示一个时间段,并可以进行计算,而且可以直接对datetime计算. 例子: today() datetime的today函数可以表示现在的时间. 例 ...
- Hibernate性能提升
1.大数据量批量插入造成Exception in thread "main" java.lang.OutOfMemoryError 内存溢出异常 正常插入: session.sav ...
- 如何防御DNS陷阱?黑客常用3种DNS欺骗手法
DNS如何被利用?那么这个系统如何让用户变得脆弱?通常解析器会告诉每个DNS服务器你正在寻找哪个域名.此请求有时会包含您的完整IP地址.或者,如果不是您的完整IP地址,请求中通常会包含您的大部分IP地 ...
- CONNECT_BY_ROOT
1.select * from EMP t where t.deptno = 10; EMPNO ENAME JOB MGR HIREDATE SAL ...
- IO操作之ObjectInputStream与ObjectOutputStream
之前写过DataInputStream和DataOutputStream,使用这两个类可以对java基本数据类型进行序列化和反序列化. 本篇再来两个新东西:ObjectInputStream,Obje ...
- Java Web学习总结(1)Tomcat使用教程
一,简介 Tomcat是一个实现了JAVA EE标准的最小的WEB服务器,是Apache 软件基金会的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.因 ...
- php quotemeta()函数 语法
php quotemeta()函数 语法 作用:在预定义字符前添加反斜杠东莞直线电机 语法:quotemeta(string) 参数: 参数 描述 string 必须,需要处理的字符串 说明:该函数可 ...
- JS中常见的几种报错类型
1.SyntaxError(语法错误) 解析代码时发生的语法错误 var 1a; //Uncaught SyntaxError: Invalid or unexpected token 变量名错误 c ...
- LUOGU P4088 [USACO18FEB]Slingshot(线段树)
传送门 解题思路 推了推式子发现是个二维数点,想了想似乎排序加线段树难写,就写了个树套树,结果写完看见空间才\(128M\)..各种奇技淫巧卡空间还是\(MLE\)到天上.后来只好乖乖的写排序+线段树 ...