解决if else的链式调用问题

问题

​ 在我们的代码中经常会出现大量的if else的情况,有些场景会出现链式的if else if,还有的业务必须按照顺序来进行if else的顺序判断,这样的代码不美观不说而且可维护性也不好。那怎么办呢?网上大部分的方案都是使用 策略者模式+函数式接口来解决问题。可以是可以,但是这样如何做到按照我想要的顺序呢?所以改进一下,策略者模式+函数式接口+责任链模式 这样可以由我们业务代码控制是否进行下次的判断等操作。

先上代码

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author: luojing
 * 解决链式判断,例如:if(){}else if(){} 和 if() if()的情况
 * T: 条件判断的入参
 * U: 执行函数的入参
 * R: 执行结束后的出参
 */
public class ChainDecide<T, U, R> {
    private final Map<Predicate<T>, Function<U, R>> functionChain = new LinkedHashMap<>();

    /**
     * 添加处理链式函数,注意添加顺序就是执行顺序
     *
     * @param conditionFunction 条件函数,就是if后面判断是否执行的条件
     * @param handleFunction    执行的函数
     */
    public void add(Predicate<T> conditionFunction, Function<U, R> handleFunction) {
        functionChain.put(conditionFunction, handleFunction);
    }

    /**
     * 处理 f(){}else if(){}的情况
     *
     * @param conditionArg 条件的入参
     * @param handleArg    执行函数的入参
     * @return 执行结果
     */
    public R handle(T conditionArg, U handleArg) {
        return handle(conditionArg, handleArg, r -> false);
    }

    /**
     * 处理 f(){}else if(){}的情况
     *
     * @param conditionArg 条件的入参
     * @param handleArg    执行函数的入参
     * @param defaultR     默认执行结果,如果条件没有判断到返回默认值
     * @return 执行结果
     */
    public R handle(T conditionArg, U handleArg, R defaultR) {
        return handle(conditionArg, handleArg, r -> false, defaultR);
    }

    /**
     * 处理 if() if()的情况
     *
     * @param conditionArg 条件的入参
     * @param handleArg    执行函数的入参
     * @param nextIf       是否执行下一个条件函数,返回true继续执行否则直接返回最后执行的结果
     * @return 执行结果
     */
    public R handle(T conditionArg, U handleArg, Predicate<R> nextIf) {
        return handle(conditionArg, handleArg, nextIf, null);
    }

    /**
     * 处理 if() if()的情况
     *
     * @param conditionArg 条件的入参
     * @param handleArg    执行函数的入参
     * @param nextIf       是否执行下一个条件函数,返回true继续执行否则直接返回最后执行的结果
     * @param defaultR     默认执行结果,如果条件没有判断到返回默认值
     * @return 执行结果
     */
    public R handle(T conditionArg, U handleArg, Predicate<R> nextIf, R defaultR) {
        for (Map.Entry<Predicate<T>, Function<U, R>> entry : functionChain.entrySet()) {
            Predicate<T> condition = entry.getKey();
            if (condition.test(conditionArg)) {
                R r = entry.getValue().apply(handleArg);
                if (!nextIf.test(r)) {
                    return r;
                }
            }
        }
        return defaultR;
    }
}

代码不难,有函数式编程经验的小伙伴应该可以很轻易读懂代码,目前主要解决的是多if并排的情况和if else if链式判断的情况。如果不满足你的需求你也可以二次开发。

测试案例

public static void main(String[] args) {
    System.out.println(operation("%", 1, 2));
}

/**
     * 运算
     *
     * @param symbol 运算符 + - * /
     * @param num1   运算第一个数
     * @param num2   运算第二个数
     * @return 结果
     */
public static Float operation(String symbol, float num1, float num2) {
    if ("+".equals(symbol)) {
        return num1 + num2;
    } else if ("-".equals(symbol)) {
        return num1 - num2;
    } else if ("*".equals(symbol)) {
        return num1 * num2;
    } else if ("/".equals(symbol)) {
        return num1 / num2;
    }
    throw new RuntimeException("运算符不被支持");
}

这是原来我们需要进行if else判断的情况,其实也可以写成if if的情况哦!别在这杠。

那么我们使用链式调用工具来试试:

private static final ChainDecide<String, OperationWapper, Float> decide = new ChainDecide();

@AllArgsConstructor
@Getter
private static class OperationWapper {
    private float num1;
    private float num2;
}

static {
    decide.add("+"::equals, operationWapper -> operationWapper.getNum1() + operationWapper.getNum2());
    decide.add("-"::equals, operationWapper -> operationWapper.getNum1() - operationWapper.getNum2());
    decide.add("*"::equals, operationWapper -> operationWapper.getNum1() * operationWapper.getNum2());
    decide.add("/"::equals, operationWapper -> operationWapper.getNum1() / operationWapper.getNum2());
//        decide.add(symbol -> true, operationWapper -> {
//            throw new RuntimeException("运算符不被支持");
//        });
}

/**
     * 运算
     *
     * @param symbol 运算符 + - * /
     * @param num1   运算第一个数
     * @param num2   运算第二个数
     * @return 结果
     */
public static Float operation1(String symbol, float num1, float num2) {
    return decide.handle(symbol, new OperationWapper(num1, num2), 0f);
}

public static void main(String[] args) {
    System.out.println(operation1("%", 1, 2));
}

是不是看出来了,代码量变多了,对是的,但是你看看代码是不是变的好看些了,如果你的if 判断过多而且处理的业务代码很长,你还会写在里面吗?你是不是应该提一个方法处理。而且代码也好维护了,加入的顺序就是判断的顺序,如果是多个if 但是每个if都要执行,那么请把 nextIf让他始终返回true就好了。

最后

这是在我工作中遇到了比较麻烦的if判断场景,最后提炼的结果,基本能满足大部分业务的if else的情况,如果有if else嵌套可以创建多个ChainDecide对象,最好把这个对象创建在外面因为程序启动加载后无需每次使用都创建。

最后,本人能力有限!如果有错误,有更好的方案或者有疑问可以联系我哦!qq:1126184155。欢迎来撩!

posted @ 2022-08-19 16:38  敬敬不想造轮子  阅读(367)  评论(0编辑  收藏  举报