详解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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Java手写一个好用的FTP操作工具类

    基于Java手写一个好用的FTP操作工具类

    网上百度了很多FTP的java 工具类,发现文章代码都比较久远,且代码臃肿,即使搜到了代码写的还可以的,封装的常用操作方法不全面。所以本文将手写一个好用的Java FTP操作工具类,需要的可以参考一下
    2022-04-04
  • Java之Spring AOP 实现用户权限验证

    Java之Spring AOP 实现用户权限验证

    本篇文章主要介绍了Java之Spring AOP 实现用户权限验证,用户登录、权限管理这些是必不可少的业务逻辑,具有一定的参考价值,有兴趣的可以了解一下。
    2017-02-02
  • 关于Shiro过滤器配置方式(ShiroFilterFactoryBean)

    关于Shiro过滤器配置方式(ShiroFilterFactoryBean)

    这篇文章主要介绍了关于Shiro过滤器配置方式(ShiroFilterFactoryBean),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 关于Java中避免空指针的方法

    关于Java中避免空指针的方法

    这篇文章主要介绍了关于Java中避免空指针的方法,空指针异常就是我们在对空对象进行的任何操作都会报空指针异常,所谓的指针,就是java中的对象的引用,比如String s;这个就是指针,需要的朋友可以参考下
    2023-07-07
  • Classloader隔离技术在业务监控中的应用详解

    Classloader隔离技术在业务监控中的应用详解

    这篇文章主要为大家介绍了Classloader隔离技术在业务监控中的应用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 入门到精通Java SSO单点登录原理详解

    入门到精通Java SSO单点登录原理详解

    这篇文章主要介绍了入门到精通Java SSO单点登录原理详解,本文主要对SSO单点登录与CAS、OAuth2.0两种授权协议的关系和原理进行详细说明
    2022-09-09
  • 网络爬虫案例解析

    网络爬虫案例解析

    本文主要介绍了网络爬虫的小案例。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • Java简单统计字符串中汉字,英文字母及数字数量的方法

    Java简单统计字符串中汉字,英文字母及数字数量的方法

    这篇文章主要介绍了Java简单统计字符串中汉字,英文字母及数字数量的方法,涉及java针对字符串的遍历、编码转换、判断等相关操作技巧,需要的朋友可以参考下
    2017-06-06
  • springboot中如何使用minio存储容器

    springboot中如何使用minio存储容器

    大家好,本篇文章主要讲的是springboot中如何使用minio存储容器,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • Java泛型类与泛型方法的定义详解

    Java泛型类与泛型方法的定义详解

    这篇文章主要介绍了Java泛型类与泛型方法的定义,结合实例形式详细分析了java泛型类与泛型方法定义、用法及相关操作注意事项,需要的朋友可以参考下
    2019-08-08

最新评论