详解Java如何优雅地书写if-else

 更新时间:2022年08月12日 16:33:14   作者:benjamin55555  
在日常开发中我们常常遇到有多个if else的情况,之间书写显得代码冗余难看,对于追求更高质量代码的同学,就会思考如何优雅地处理这种代码。本文我们就来探讨下几种优化if else的方法

0. 引言

在日常开发中我们常常遇到有多个if else的情况,之间书写显得代码冗余难看,对于追求更高质量代码的同学,就会思考如何优雅地处理这种代码

下面我们来探讨下几种优化if else的方法

1. switch

switch方法针对枚举值处理有不错的效果,比如针对不同的订单状态时要做不同的处理,因为状态值有限,这时我们就可以直接使用switch来针对不同状态做不同的处理:

原语句

public void before(Integer status) {
        if(status == 1){
            System.out.println("订单未接单");
        }else if(status == 2){
            System.out.println("订单未发货");
        }else if(status == 3){
            System.out.println("订单未签收");
        }else{
            System.out.println("订单已签收");
        }
    }

switch

public void greater(Integer status) {
        switch (status){
            case 1:
                System.out.println("订单未接单");
                break;
            case 2:
                System.out.println("订单未发货");
                break;
            case 3:
                System.out.println("订单未签收");
                break;
            default:
                System.out.println("订单已签收");
        }
    }

总结:

switch语句适用于判断条件有限且不需要经过复杂的计算,处理语句简单的场景。如果我们的判断条件需要经过一系列复杂的计算才能得到,或者处理语句逻辑也比较复杂时,我们就要考虑其他的处理方式了,毕竟在case中书写一大堆处理语句并不算得让人舒适的事情

2. 函数式接口

针对比较复杂的处理逻辑时,我们偏向于将这些处理逻辑单独抽离出来,而不是还放在一个方法里处理,增加整体的可读性和解耦性,也是我们衍生出利用函数式接口来处理if else的模式

函数式接口map处理if else的要义,是将各个条件的复杂处理逻辑单独抽取为一个函数式接口方法,通过统一的判断条件来调用不同的方法,具体示例如下

@Component
public class FunctionInterfaceStrategy {

    /**
     * key 方法参数,多个参数可以自定义一个实体类处理
     * value 方法返回值
     */
    private Map<Integer, Function<Object,Boolean>> operationMap;

    @PostConstruct
    private void init(){
        operationMap = new HashMap<>();
        operationMap.put(1,this::takeOrder);
        operationMap.put(2,this::sendOrder);
        operationMap.put(3,this::signOrder);
        operationMap.put(4,this::finishOrder);
    }

    public Boolean doOperation(Object params,Integer status){
        return operationMap.get(status) == null || operationMap.get(status).apply(params);
    }

    private Boolean takeOrder(Object params){
        // TODO 比较复杂的处理逻辑
        System.out.println("订单未接单");
        return true;
    }

    private Boolean sendOrder(Object params){
        // TODO 比较复杂的处理逻辑
        System.out.println("订单未发货");
        return true;
    }

    private Boolean signOrder(Object params){
        // TODO 比较复杂的处理逻辑
        System.out.println("订单未签收");
        return true;
    }

    private Boolean finishOrder(Object params){
        // TODO 比较复杂的处理逻辑
        System.out.println("订单已签收");
        return true;
    }

}

调用时就不用再用if else区分了,直接传入参数到function map中调用

   @Autowired
    private FunctionInterfaceStrategy functionInterfaceStrategy;
    
    
    functionInterfaceStrategy.doOperation("参数",1);

当然我们上述演示的是有参数有返回值的函数式接口,实际生产中我们可能还需要其他形式的函数式接口,我们将其单独罗列出来,供大家参考使用

接口名称说明调用方法
Supplier无参数,有返回值get
Consumer有参数,无返回值accept
Runnable无参数,无返回值run
Function有参数,有返回值apply

3. 策略模式

上述的函数式接口的形式,实际上是针对方法进行了分离,所有的实现方法还是放在了一个类里,即使你可以在FunctionInterfaceStrategy类中通过依赖注入的形式再次调用其他类的方法,但是这样的模式,已经趋近于我们要将的下一种方法,即使用策略模式来解决 if else

策略模式的形式适用于实现方法更加复杂的情况,需要将处理逻辑解耦的更加干净的场景

1、首先我们需要创建一个接口类,用来规定我们后续的实现类的格式

public interface OrderStrategy {

    /**
     * 获取实现类标识
     * @return
     */
    Integer getType();

    /**
     * 逻辑处理
     * @param params
     * @return
     */
    Boolean handler(Object params);

}

2、其次针对每个判断条件创建一个实现类

@Service
public class SendOrderStrategy implements OrderStrategy{

    @Override
    public Integer getType() {
        return 2;
    }

    @Override
    public Boolean handler(Object params) {
        // TODO 复杂的处理逻辑
        System.out.println("订单未发货");
        return true;
    }
}

@Service
public class SignOrderStrategy implements OrderStrategy{

    @Override
    public Integer getType() {
        return 3;
    }

    @Override
    public Boolean handler(Object params) {
        // TODO 复杂的处理逻辑
        System.out.println("订单未签收");
        return true;
    }
}

@Service
public class TakeOrderStrategy implements OrderStrategy{

    @Override
    public Integer getType() {
        return 1;
    }

    @Override
    public Boolean handler(Object params) {
        // TODO 复杂的处理逻辑
        System.out.println("订单未接单");
        return true;
    }
}

3、创建一个策略工厂类,承装实现类

@Component
@AllArgsConstructor
public class OrderStrategyFactory {

    private final List<OrderStrategy> orderStrategyList;

    private static Map<Integer,OrderStrategy> strategyMap = new HashMap<>();

    @PostConstruct
    private void init(){
        for (OrderStrategy orderStrategy : orderStrategyList) {
            strategyMap.put(orderStrategy.getType(),orderStrategy);
        }
    }

    /**
     * 执行方法
     * @param status
     * @param params
     * @return
     */
    public Boolean handler(Integer status,Object params){
        return strategyMap.get(status).handler(params);
    }

}

4、方法调用

@RestController
@RequestMapping("ifelse")
@AllArgsConstructor
public class IfElseController {

    private final OrderStrategyFactory orderStrategyFactory;

    @GetMapping("strategy")
    public Boolean strategy(Integer status){
        return orderStrategyFactory.handler(status,"1");
    }

}

总结:

通过上述的代码示例,大家其实可以发现,函数式接口和策略模式有异曲同工之处,根本区别在于是否需要将实现方法单独抽取为一个实现类。抽取的粒度越细也就说明解耦越强

使用策略模式,后续如果需要增加if else条件的话,只需要增加实现类即可,针对后续的处理更加方便

最终使用哪一个还需要根据具体的业务情况而定

4. 卫语句

我们经常需要在方法前处理各种参数嵌套判断逻辑,如果不满足条件就直接返回了,这种情况更加推荐使用卫语句来处理

原语句

    public void before(Integer status) {
        if(status != null) {
            if(status != 0){
                if(status == 1){
                    System.out.println("订单未接单");
                }
            }
        }
    }

卫语句

    public void greater(Integer status) {
        if(status == null){
            return;
        }
        if(status != 0){
            return;
        }
        if(status == 1){
            System.out.println("订单未接单");
        }
    }

到此这篇关于详解Java如何优雅地书写if-else的文章就介绍到这了,更多相关Java if-else内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot+Redis使用AOP防止重复提交的实现

    SpringBoot+Redis使用AOP防止重复提交的实现

    本文主要介绍了SpringBoot+Redis使用AOP防止重复提交的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • SpringMVC结合ajaxfileupload实现文件无刷新上传代码

    SpringMVC结合ajaxfileupload实现文件无刷新上传代码

    本篇文章主要介绍了SpringMVC结合ajaxfileupload实现文件无刷新上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • SpringBoot整合rockerMQ消息队列详解

    SpringBoot整合rockerMQ消息队列详解

    今天和大家一起深入生产级别消息中间件 - RocketMQ 的内核实现,来看看真正落地能支撑万亿级消息容量、低延迟的消息队列到底是如何设计的。我会先介绍整体的架构设计,然后再深入各核心模块的详细设计、核心流程的剖析
    2022-07-07
  • IntelliJ IDEA创建maven多模块项目(图文教程)

    IntelliJ IDEA创建maven多模块项目(图文教程)

    这篇文章主要介绍了IntelliJ IDEA创建maven多模块项目(图文教程),非常具有实用价值,需要的朋友可以参考下
    2017-09-09
  • 10个Java文件操作必备技巧分享

    10个Java文件操作必备技巧分享

    在我们日常的开发中,文件操作是一个非常重要的主题。文件读写、文件复制、任意位置读写、缓存等技巧都是我们必须要掌握的。本文为大家整理了10个实用的文件操作技巧,希望对大家有所帮助
    2023-04-04
  • Spring Boot如何支持嵌入式Servlet容器

    Spring Boot如何支持嵌入式Servlet容器

    这篇文章主要介绍了Spring Boot如何支持嵌入式Servlet容器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 在ssm中使用ModelAndView跳转页面失效的解决

    在ssm中使用ModelAndView跳转页面失效的解决

    这篇文章主要介绍了在ssm中使用ModelAndView跳转页面失效的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Spring如何处理注解的深入理解

    Spring如何处理注解的深入理解

    这篇文章主要给大家介绍了关于Spring如何处理注解的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java中的注解具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Spring Boot定时+多线程执行过程解析

    Spring Boot定时+多线程执行过程解析

    这篇文章主要介绍了Spring Boot定时+多线程执行过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Java实现 基于密度的局部离群点检测------lof算法

    Java实现 基于密度的局部离群点检测------lof算法

    这篇文章主要介绍了Java实现 基于密度的局部离群点检测------lof算法,本文通过算法概述,算法Java源码,测试结果等方面一一进行说明,以下就是详细内容,需要的朋友可以参考下
    2021-07-07

最新评论