Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >if-else 判断语句过多该如何处理?

if-else 判断语句过多该如何处理?

作者头像
Java极客技术
发布于 2022-12-04 02:40:37
发布于 2022-12-04 02:40:37
62701
代码可运行
举报
文章被收录于专栏:Java极客技术Java极客技术
运行总次数:1
代码可运行

一、简介

我们平时在写代码的时候,if-else判断语句基本上必不可少,当我们的判断语句只有一两层的时候,类似下面这种,情况还好,基本上能接受;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(condition){
    doSomeThing();
} else {
 doSomeThing();
}

但是当过度的使用if-else的时候,会对代码的可读性、可扩展性造成负面影响,比如类似下面这个!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(condition1){
    if(condition2){
        if(condition3){
            if(condition4){
                if(condition5){
                    if(condition6){
                        doSomeThing();
                    }
                }
            }
        }
    }
}

如果判断语句越来越多,后期进行项目维护也会比较困难,对于后面接手项目的人来说,会是一个很头疼的问题了。

因此,如何去除掉代码中过多的if...else语句,反映的是程序员对软件重构、设计模式、面向对象设计、架构模式、数据结构等多方面技术的综合运用能力。

那问题来了,如何解决代码中过多的if...else语句呢?下面一起来聊聊有效的几种解决方案!

二、解决方案

首先,我们编写一个简单的程序计算器,代码如下!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public int calculate(int a, int b, String operator) {
    int result = Integer.MIN_VALUE;

    if ("add".equals(operator)) {
        result = a + b;
    } else if ("multiply".equals(operator)) {
        result = a * b;
    } else if ("divide".equals(operator)) {
        result = a / b;
    } else if ("subtract".equals(operator)) {
        result = a - b;
    }
    return result;
}

以上文为案例,我们一起来看看,可以对其进行改造的几种方式!

2.1、适时的 return

如果if里面条件判断比较单一又互斥的,我们可以在合适的位置直接return,废除掉else代码,比如将其改造成如下方式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public int calculate(int a, int b, String operator) {
    if ("add".equals(operator)) {
        return a + b;
    }
    if ("subtract".equals(operator)) {
        return a - b;
    }
    if ("multiply".equals(operator)) {
        return a * b;
    }
    if ("divide".equals(operator)) {
        return a / b;
    }
    return ;
}

代码瞬间是不是清晰了很多!

2.2、引入策略模式进行改造

但是当if判断逻辑内容非常复杂的时候,以上的方案就有点不够优雅了,这个时候,我们可以将if判断逻辑独立成类来单独处理,操作方法如下!

  • 首先,我们定义一个Operation接口,用于逻辑的计算
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Operation {

    /**
     * 执行计算
     * @param a
     * @param b
     * @return
     */
    int execute(int a, int b);
}
  • 接着,分别将四个if判断逻辑独立成一个模块,来单独处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class AddOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a + b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class SubOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a - b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class MultiOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a * b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DivOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a / b;
    }
}
  • 然后,创建一个工厂类,用于处理客户端传入的参数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class OperatorFactory {

    private static Map<String, Operation> operationMap = new HashMap<>();

    static {
        //初始化实现类
        operationMap.put("add", new AddOperation());
        operationMap.put("sub", new SubOperation());
        operationMap.put("multi", new MultiOperation());
        operationMap.put("div", new DivOperation());
        // more operators
    }

    /**
     * 获取对应的目标实现类
     * @param operator
     * @return
     */
    public static Optional<Operation> getOperation(String operator){
        return Optional.ofNullable(operationMap.get(operator));
    }

}
  • 最后,在需要的地方引入方法即可!
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class OperatorTestMain {

    public static void main(String[] args) {
        //获取计算的目标实现类
        Operation targetOperation = OperatorFactory
                .getOperation("add")
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        int result = targetOperation.execute(, );
        System.out.println("result:" +  result);
    }
}

至此,if...else方法改造完毕!

2.3、引入规则引擎模式进行改造

当方法内部的if...else越来越多的时候,我们可以通过规则引擎模式来消除这种复杂度,具体实践如下!

  • 首先,创建一个规则标准接口Rule,并将条件判断方法进行抽象
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Rule {

    /**
     * 检查是否进入规则计算
     * @param expression
     * @return
     */
    boolean evaluate(Expression expression);


    /**
     * 执行规则计算
     * @param expression
     * @return
     */
    int execute(Expression expression);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Expression {

    private Integer a;

    private Integer b;

    /**
     * 计算类型
     */
    private String operator;

    public Expression(Integer a, Integer b, String operator) {
        this.a = a;
        this.b = b;
        this.operator = operator;
    }
}
  • 接着,根据每个规则创建不同的计算实现类,以AddRule为例
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class AddRule implements Rule {

    @Override
    public boolean evaluate(Expression expression) {
        if ("add".equalsIgnoreCase(expression.getOperator())) {
            return true;
        }
        return false;
    }

    @Override
    public int execute(Expression expression) {
        int result = expression.getA() + expression.getB();;
        return result;
    }
}
  • 然后,创建一个规则引擎,用于逻辑的处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RuleEngine {

    private static List<Rule> rules = new ArrayList<>();

    static {
        rules.add(new AddRule());
        //添加其他的规则计算实现类
    }


    /**
     * 执行规则计算
     * @param expression
     * @return
     */
    public int process(Expression expression){
        Rule rule = rules
                .stream()
                .filter(r -> r.evaluate(expression))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
        return rule.execute(expression);
    }

}
  • 最后,在需要的地方引入方法即可!
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RuleEngineTestMain {

    public static void main(String[] args) {
        Expression expression = new Expression(, , "add");
        RuleEngine engine = new RuleEngine();
        int result = engine.process(expression);
        System.out.println("result:" +  result);
    }
}

规则引擎和策略模式,最大的不同的就是将条件逻辑判断抽象化,由具体的实现类来判断是不是满足要求,如果满足要求,就执行;否则不执行!

三、Spring 集成应用

可能有的同学会发出疑问,以上介绍的都是原生的处理办法,在当下处处都集成了Spring框架的项目,我们应该如何使用呢?

下面我们以上面提到的《引入策略模式进行改造》为例,如果在Spring里面,我们应该如何应用?

3.1、Spring 策略模式实现介绍(方案一)
  • 首先,我们还是定义一个Command接口,用于方法的抽象和统一
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Command {

    /**
     * 命令类型
     * @return
     */
    String operateType();

    /**
     * 执行
     * @param a
     * @param b
     * @return
     */
    Integer execute(int a, int b);

}
  • 接着,编写四套不同的计算处理逻辑
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class AddCommand implements Command {

    @Override
    public String operateType() {
        return "add";
    }

    @Override
    public Integer execute(int a, int b) {
        return a + b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class SubCommand implements Command {

    @Override
    public String operateType() {
        return "subtract";
    }

    @Override
    public Integer execute(int a, int b) {
        return a - b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class MultiCommand implements Command {

    @Override
    public String operateType() {
        return "multiply";
    }

    @Override
    public Integer execute(int a, int b) {
        return a * b;
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class DivCommand implements Command {

    @Override
    public String operateType() {
        return "divide";
    }

    @Override
    public Integer execute(int a, int b) {
        return a / b;
    }
}
  • 然后,编写一个类似于上文的策略处理类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class CalculatorService implements ApplicationContextAware {

    private Map<String, Command> commandMap = new ConcurrentHashMap<>();


    /**
     * 执行计算
     * @param operateType
     * @param a
     * @param b
     * @return
     */
    public int calculate(String operateType,int a, int b){
        Command targetCommand = Optional.ofNullable(commandMap.get(operateType))
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        return targetCommand.execute(a,b);
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Command> tempMap = applicationContext.getBeansOfType(Command.class);
        tempMap.values().forEach(source -> commandMap.put(source.operateType(), source));
    }

}
  • 最后,我们只需要在适当的位置应用即可!
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private CalculatorService calculatorService;

    @Test
    public void test(){
        int result = calculatorService.calculate("add", ,);
        System.out.println("result:" +  result);
    }
}
3.2、Spring 策略模式实现介绍(方案二,推荐)

翻查Springioc容器,你会发现一个秘密,当一个接口有多个实现类时,Spring会自动将Strategy接口的实现类注入到这个Map中,keybean idvalue值则为对应的策略实现类。

简单的说,我们只需要通过@Autowired注入对象,不需要通过CalculatorService这个类进行单独配置,操作方式如下!

  • 首先,编写一个CommandFactory工厂类,用于逻辑的处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class CommandFactory {

    /**
     * Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
     */
    @Autowired
    private Map<String, Command> commandMap;


    /**
     * 执行计算
     * @param operateType
     * @param a
     * @param b
     * @return
     */
    public int calculate(String operateType,int a, int b){
        Command targetCommand = Optional.ofNullable(commandMap.get(operateType))
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        return targetCommand.execute(a,b);
    }
}
  • 最后,直接在合适的地方使用CommandFactory即可!
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private CommandFactory commandFactory;

    @Test
    public void test(){
        int result = commandFactory.calculate("addCommand", ,);
        System.out.println("result:" +  result);
    }
}

四、小结

本文主要围绕如何解决if...else...过多问题进行一些总结和案例分享,期望能对大家有所帮助!

五、参考

1、baeldung java-replace-if-statements

2、知乎 - 如何去除代码中过多的if语句

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java极客技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
实战讲解,原来是用 SpringBoot 实现策略模式可以这么简单
一说起策略设计模式,相比大家都不陌生,在实际的业务开发中,合理的使用设计模式来编程,可以让代码阅读起来层次感更强,同时扩展性也会得到提升!
Java极客技术
2022/12/04
3.5K2
Java中的大量if else语句的替代方案
之前写过转载过一篇类似的不错的文章《除代码中的 if-else/switch-case的正确姿势》https://blog.csdn.net/w605283073/article/details/89117561,
明明如月学长
2021/08/31
2.1K0
Java中多个ifelse语句的替代设计
ifelse是任何编程语言的重要组成部分。但是我们编写了大量嵌套的if语句,这使得我们的代码更加复杂和难以维护。
王知无-import_bigdata
2019/07/01
3.6K0
常见重构技巧 - 去除多余的if else
原文链接:https://pdai.tech/md/develop/refactor/dev-refactor-if-else.html
鱼找水需要时间
2023/02/16
4490
常见重构技巧 - 去除多余的if else
Java中大量if...else语句的消除替代方案
在我们平时的开发过程中,经常可能会出现大量If else的场景,代码显的很臃肿,非常不优雅。那我们又没有办法处理呢?
攻城狮的那点事
2019/12/25
2.5K0
Java中大量if...else语句的消除替代方案
探讨if...else的替代方案
假设我们要做一个计算器,实现加减乘除的需求。使用if...else...语句实现代码如下:
互联网金融打杂
2022/08/01
2.5K0
探讨if...else的替代方案
java工厂模式实例(设计模式)「建议收藏」
如果使用java语言来描述则是,对具有相同动作,不同动作执行过程的一
全栈程序员站长
2022/09/09
8400
java工厂模式实例(设计模式)「建议收藏」
常见代码重构技巧(非常实用)
项目在不断演进过程中,代码不停地在堆砌。如果没有人为代码的质量负责,代码总是会往越来越混乱的方向演进。当混乱到一定程度之后,量变引起质变,项目的维护成本已经高过重新开发一套新代码的成本,想要再去重构,已经没有人能做到了。
肉眼品世界
2021/05/10
9620
常见代码重构技巧(非常实用)
Java经典设计模式之十一种行为型模式(附实例和详解)
Java经典设计模式共有21中,分为三大类:创建型模式(5种)、结构型模式(7种)和行为型模式(11种)。
全栈程序员站长
2022/06/29
3820
Java经典设计模式之十一种行为型模式(附实例和详解)
代码重构的原则和技巧
项目在不断演进过程中,代码不停地在堆砌。如果没有人为代码的质量负责,代码总是会往越来越混乱的方向演进。当混乱到一定程度之后,量变引起质变,项目的维护成本已经高过重新开发一套新代码的成本,想要再去重构,已经没有人能做到了。
架构之家
2022/07/12
6580
代码重构的原则和技巧
简单规则引擎Easy-Rule性能测试
要进行Easy Rules和普通策略模式的性能比较,需要有一个具体的案例来测试两种方法在不同条件下的运行速度。以下是一个简单的案例来比较它们的性能:
Antony
2023/07/04
1K0
简单规则引擎Easy-Rule性能测试
设计模式(Design Patterns)Java版
——可复用面向对象软件的基础
sunsky
2020/08/20
3800
这个无敌设计,可以解析并运算任意数学表达式
然后分别创建非终结符表达式角色加、减、乘、除解释器,加法运算表达式AddInterpreter类的代码如下。
Tom弹架构
2021/11/18
5660
Dubbo:服务路由的实现
上一篇中,我们介绍了dubbo的负载均衡实现,见识了几种常用的负载均衡算法。就单个功能而言,似乎dubbo并没有太多的突出之处。事实上,一个成功的产品不必每个地方都要打破常规。更重要的是其全局优化的架构设计,以及如何使用现有的优秀解决方案为己服务。
烂猪皮
2022/12/16
9350
Java优化_解决if嵌套过多
彻底消灭if-else嵌套 设计模式-策略模式 如何干掉 Spring Boot 中大片的 if else? 业务代码中, if else 使用策略模式优化 设计模式 策略模式 极简策略模式 (妙用枚举) 责任链模式+策略模式
全栈程序员站长
2022/09/29
2.1K0
easy-rules小试牛刀
easy-rules-core-3.1.0-sources.jar!/org/jeasy/rules/api/Rule.java
code4it
2018/09/17
2.1K0
8种优化if-else代码的方案请拿走
代码中如果if-else比较多,阅读起来比较困难,维护起来也比较困难,很容易出bug,接下来,本文将介绍优化if-else代码的八种方案。
用户4172423
2020/03/12
1.4K0
Java | if-else代码优化方案
如果if-else代码块包含return语句,可以考虑通过提前return,把多余else⼲掉,使代码更加优雅。
Java小技巧
2022/05/23
5880
【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼?
之前为了学习设计模式,看过网上很多相关博客讲解,大都是画下UML类图,举例几个毫不相干的demo,看了几遍仍然是云里雾里。
一枝花算不算浪漫
2019/12/17
1.6K0
【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼?
行为型-Interpreter
命令模式的原理解读命令模式的英文翻译是 Command Design Pattern。在 GoF 的《设计模式》一书中,它是这么定义的:
acc8226
2022/05/17
3160
相关推荐
实战讲解,原来是用 SpringBoot 实现策略模式可以这么简单
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档