Java中大量if...else语句的消除替代方案
在我们平时的开发过程中,经常可能会出现大量If else的场景,代码显的很臃肿,非常不优雅。那我们又没有办法处理呢?
针对大量的if嵌套让代码的复杂性增高而且难以维护。本文将介绍多种解决方案。
案例
下面模拟业务逻辑,根据传入的条件作出不同的处理方式。
拿一个计算器类当做案例,有加减乘除四种方法,输出结果和四种操作有关。
- 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;
- }
当然也可以用switch来实现。
- public int calculateUsingSwitch(int a, int b, String operator) {
- switch (operator) {
- case "add":
- result = a + b;
- break;
- // other cases
- }
- return result;
- }
随着条件越来越多,复杂性也增高,也越来越难以维护。
重构
1、工厂类我们将操作进行抽象给出一个操作接口
- public interface Operation {
- int apply(int a, int b);
- }
然后实现加减乘除四个方法
- public class Addition implements Operation {
- @Override
- public int apply(int a, int b) {
- return a + b;
- }
- }
然后通过操作工厂提供操作
- public class OperatorFactory {
- static Map<String, Operation> operationMap = new HashMap<>();
- static {
- operationMap.put("add", new Addition());
- operationMap.put("divide", new Division());
- // more operators
- }
- public static Optional<Operation> getOperation(String operator) {
- return Optional.ofNullable(operationMap.get(operator));
- }
- }
调用
- public int calculateUsingFactory(int a, int b, String operator) {
- Operation targetOperation = OperatorFactory
- .getOperation(operator)
- .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
- return targetOperation.apply(a, b);
- }
新增操作只需要维护操作工厂的operationMap即可。
2、使用枚举
在枚举中定义操作,如下:
- public enum Operator {
- ADD, MULTIPLY, SUBTRACT, DIVIDE
- }
然而不同的操作对应的逻辑不一样,我们编写抽象方法
- ADD {
- @Override
- public int apply(int a, int b) {
- return a + b;
- }
- },
- // other operators
- public abstract int apply(int a, int b);
调用时直接传入枚举值
- public int calculate(int a, int b, Operator operator) {
- return operator.apply(a, b);
- }
- @Test
- public void whenCalculateUsingEnumOperator_thenReturnCorrectResult() {
- Calculator calculator = new Calculator();
- int result = calculator.calculate(3, 4, Operator.valueOf("ADD"));
- assertEquals(7, result);
- }
3、命令模式
定义命令接口。
- public interface Command {
- Integer execute();
- }
实现加法
- public class AddCommand implements Command {
- // Instance variables
- public AddCommand(int a, int b) {
- this.a = a;
- this.b = b;
- }
- @Override
- public Integer execute() {
- return a + b;
- }
- }
定义一个Calculator类,加入执行命令的方法。
- public int calculate(Command command) {
- return command.execute();
- }
测试代码
- @Test
- public void whenCalculateUsingCommand_thenReturnCorrectResult() {
- Calculator calculator = new Calculator();
- int result = calculator.calculate(new AddCommand(3, 7));
- assertEquals(10, result);
- }
4、规则引擎
定义规则接口
- public interface Rule {
- boolean evaluate(Expression expression);
- Result getResult();
- }
实现规则引擎
- public class RuleEngine {
- private static List<Rule> rules = new ArrayList<>();
- static {
- rules.add(new AddRule());
- }
- public Result process(Expression expression) {
- Rule rule = rules.stream()
- .filter(r -> r.evaluate(expression))
- .findFirst()
- .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule"));
- return rule.getResult();
- }
- }
定义表达式
- public class Expression {
- private Integer x;
- private Integer y;
- private Operator operator;
- }
定义加法规则
- public class AddRule implements Rule {
- @Override
- public boolean evaluate(Expression expression) {
- boolean evalResult = false;
- if (expression.getOperator() == Operator.ADD) {
- this.result = expression.getX() + expression.getY();
- evalResult = true;
- }
- return evalResult;
- }
- }
给规则引擎传入表达式来调用
- @Test
- public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult() {
- Expression expression = new Expression(5, 5, Operator.ADD);
- RuleEngine engine = new RuleEngine();
- Result result = engine.process(expression);
- assertNotNull(result);
- assertEquals(10, result.getValue());
- }
总结虽然说常见的代码中if...else不可避免,但滥用 if...else 会对代码的可读性、可维护性造成很大伤害。因此,使用好 if...else,让代码清爽对于你的项目长远考虑有十分重要的意义。
英文原文:https://www.baeldung.com/java-replace-if-statements
其他参考资料:
策略设计模式:http://www.runoob.com/design-pattern/strategy-pattern.html
命令设计模式:http://www.runoob.com/design-pattern/command-pattern.html
推荐阅读:
扫码关注公众号,发送关键词获取相关资料:
发“Springboot”领取电商项目实战源码;
发“SpringCloud”领取学习实战资料;
Java中大量if...else语句的消除替代方案的更多相关文章
- 【转】Java中try catch finally语句中含有return语句的执行情况(总结版)
Java中try catch finally语句中含有return语句的执行情况(总结版) 有一点可以肯定,finally块中的内容会先于try中的return语句执行,如果finall语句块中也有r ...
- java中的Switch case语句
java中的Switch case 语句 在Switch语句中有4个关键字:switch,case break,default. 在switch(变量),变量只能是整型或者字符型,程序先读出这个变量的 ...
- Java中try、finally语句中有return时的执行情况 [转]
原文:http://kingj.iteye.com/blog/1436761 在Java中当try.finally语句中包含return语句时,执行情况到底是怎样的,finally中的代码是否执行,大 ...
- Java中try catch finally语句中含有return语句的执行情况(总结版)
在这里看到了try >但有一点是可以肯定的,finally块中的内容会先于try中的return语句执行,如果finall语句块中也有return语句的话,那么直接从finally中返回了,这也 ...
- Java中try catch finally语句中含有return语句的执行情况
finally块中的内容会先于try中的return语句执行,如果finall语句块中也有return语句的话,那么直接从finally中返回了,这也是不建议在finally中return的原因.下面 ...
- Java中try catch finally语句中含return语句的执行情况总结-编程陷阱
前言:有java编程基础的人对java的异常处理机制都会有一定了解,而且可能感觉使用起来也比较简单,但如果在try catch finally语句块中遇到return语句,开发者可能就会遇到一些逻辑问 ...
- Java | 在 Java 中执行动态表达式语句: 前中后缀、Ognl、SpEL、Groovy、Jexl3
在一些规则集或者工作流项目中,经常会遇到动态解析表达式并执行得出结果的功能. 规则引擎是一种嵌入在应用程序中的组件,它可以将业务规则从业务代码中剥离出来,使用预先定义好的语义规范来实现这些剥离出来的业 ...
- java 中 printf()语句的理解
对print和println的理解很简单,今天突然接触到printf(),有点懵,整理了下也帮自己理一理 printf是格式化输出的形式 下在举个例子: package other; public c ...
- Java中循环与选择语句
public class Ifelse{ public static void main(String [] args){ int score=98; if(score>=90&& ...
随机推荐
- 集合 Enumerable Enumerator yield
集合: 通过索引来访问成员,--引申到索引器 的使用 for foreach循环遍历 --引申到 IEnumerable IEnumerator(会引申到yield) 常用的集合操作,add, ins ...
- C# 从零开始写 SharpDx 应用 画三角
原文:C# 从零开始写 SharpDx 应用 画三角 版权声明:博客已迁移到 https://blog.lindexi.com 欢迎访问.如果当前博客图片看不到,请到 https://blog.lin ...
- 【批量添加】-SqlBulkCopy语句 标签: sql批量添加 2015-12-20 14:39 1367人阅读 评论(33)
上篇博客我们介绍了通过拼接sql字符串的方法来对sql数据库进行批量添加,但是通过语句拼接insert语句有个缺点,就是每次最多只能添加1000条.当时我们另外一个界面也用到了批量添加,但是这个界面轻 ...
- Java练习 SDUT-1239_水仙花数
水仙花数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花 ...
- @gym - 101137K@ Knights of the Old Republic
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 N 个点 M 条边的一张图. 每个点有两个属性 Ai, B ...
- jQuery Callback
Callback 函数在当前动画 100% 完成之后执行. jQuery 动画的问题 许多 jQuery 函数涉及动画.这些函数也许会将 speed 或 duration 作为可选参数. 例子:$(& ...
- PyTorch入门学习(二):Autogard之自动求梯度
autograd包是PyTorch中神经网络的核心部分,简单学习一下. autograd提供了所有张量操作的自动求微分功能. 它的灵活性体现在可以通过代码的运行来决定反向传播的过程, 这样就使得每一次 ...
- HZOJ 回家
这篇博客大部分在写我的错解……明明很简单的一道题,知道正解后10分钟AC,然而几个错解打的想死…… 错解1 WA40: 鬼知道这40分哪来的……这也是考试最后很无奈地交上去的代码,最后剩20分钟时发现 ...
- OpenResty,X-WAF防火墙相关
>>OpenResty<< >>Lua教程<< >>反向代理百度百科<< >>X-WAF配置指南<<
- hdu 1430 魔板 (BFS+预处理)
Problem - 1430 跟八数码相似的一题搜索题.做法可以是双向BFS或者预处理从"12345678"开始可以到达的所有状态,然后等价转换过去直接回溯路径即可. 代码如下: ...