Why

if/else 虽然简单易用,但在复杂逻辑场景下,不便于阅读和理解,同时不便于后期扩展。我们可以通过使用职责链模式+模版模式来代替 if/else。 下面通过一个例子来说明。

How

  • 案例

输入一个 1-1000 的数值 N,如果 N 是 3 或者 3 的倍数时,返回“FIZZ”;如果 N 是 5 或者 5 的倍数时, 返回“BUZZ”;既是 3 的倍数又是 5 的倍数时, 返回“FIZZBUZZ”;其他的则输出 N。

  • 使用if/else 实现:

    1. public String say(int input) throws Exception {
    2. if ( input < 1 || input > 1000){
    3. throw new Exception("Invalid input");
    4. }
    5. if (input % 15 == 0) {
    6. return "FIZZBUZZ";
    7. }
    8. if (input % 5 == 0) {
    9. return "BUZZ";
    10. }
    11. if (input % 3 == 0) {
    12. return "FIZZ";
    13. }
    14. return String.valueOf(input);
    15. }

    嗅一嗅其中的坏味道,如果将来需求扩展,比如引进 7 的倍数。照此逻辑,继续添加 if,问题是解决了,但总有一天你会怀疑人生!

  • 改进一:使用职责链模式+模版模式

640.png

public String say(int input) throws Exception {
    if (input < 1 || input > 1000) {
        throw new Exception("Invalid input");
    }
    DefaultParser defaultParser = new DefaultParser(null);
    MultiOfThreeParser multiOfThreeParser = new MultiOfThreeParser(defaultParser);
    MultiOfFiveParser multiFiveParser = new MultiOfFiveParser(multiOfThreeParser);
    MultiOfFifteenParser fifteenPaser = new MultiOfFifteenParser(multiFiveParser);
    return fifteenPaser.parse(input);
}
//---------------------------------------------------------------------

public abstract class Parser {
    abstract boolean isFixedResponsibility(int inputContext);
    abstract String response(int inputContext) throws Exception;

    public String parse(int inputContext) throws Exception  {
        if (isFixedResponsibility(inputContext))     {
            return response(inputContext);
        }
        if (nextParser != null) {
            return nextParser.parse(inputContext);
        }
        return NULL;
    }
}

public class MultiOfFifteenParser extends Parser {
    public MultiOfFifteenParser(Parser nextParser) {
        super(nextParser);
    }

    @Override
    public String response(int inputContext) throws Exception {
        return FLAG_FOR_MULIT_OF_FIFTEEN;
    }

    @Override
    boolean isFixedResponsibility(int inputContext)    {
        return inputContext % 15 == 0;
    }    
}

其实上述改进还存在细微的小问题,那就是 say 方法里面的异常分支处理。怎么还存在一个 if,对于一个完美主义强迫症患者而言,它的存在就是一个灾难。继续改进一下。

  • 改进二:彻底面向对象

640-1.png

public String say(int input) throws Exception {
    DefaultParser defaultParser = new DefaultParser(null);
    MultiOfThreeParser multiOfThreeParser = new MultiOfThreeParser(defaultParser);
    MultiOfFiveParser multiOfFiveParser = new MultiOfFiveParser(multiOfThreeParser);
    MultiOfFifteenParser FifteenPaser = new MultiOfFifteenParser(multiOfFiveParser);
    InvalidNumberParser invalidNumberPaser = new InvalidNumberParser(FifteenPaser);
    return invalidNumberPaser.parse(input);
}

public class InvalidNumberParser extends Parser {
    public InvalidNumberParser(Parser nextParser) {
        super(nextParser);
    }

    @Override
    String response(int inputContext) throws Exception {
        throw new Exception("Invalid input");
    }

    @Override
    boolean isFixedResponsibility(int inputContext){
        return (inputContext < L_THRESHOLD) || (inputContext > H_THRESHOLD);
    }
}

原文链接