坐地铁打折问题

前言:昨天一个初学java的同事问了我一个这样的问题,if else太多了真的好难看啊,我回答的是这个要看你的需求是什么样的,前期如果if else并且你对需求的理解不是很深的情况下可以这样写,后期如果有新需求的话再对这段逻辑进行重构(使用工厂模式+策略模式实现)。

同事的题目与代码如下:


这种写法是初学者最简单的用法,也最清晰,但是如果真的应用到项目中,这样的代码并不好,如果后期需求添加,会有更多的if else出现,那样维护的人就会很难受。不但可读性不高,看起来也不好看。

我仔细的琢磨了一下,这其实就是简单的多种情况下算数的问题,于是对这段代码进行了优化:

1.首先定义一个枚举类,将所有的情况列举出来,后面通过将条件拼接成字符串,再对条件进行判断。

public enum Train {
        LESS_THAN_100(0, ">", 100, "<=") {
            @Override
            public double calculate(double total) {
                return total;
            }
        },
        _100_150(100, ">", 150, "<") {
            @Override
            public double calculate(double total) {
                double m1 = 100;
                double m2 = (total - 100) * 0.8;
                return m1 + m2;
            }
        },
        _150_300(150, ">=", 300, "<=") {
            @Override
            public double calculate(double total) {
                double m1 = 100;
                double m2 = 49 * 0.8;
                double m3 = (total - 149) * 0.5;
                return m1 + m2 + m3;
            }
        },
        GRATER_THAN_300(300, ">", 100000, "<=") {
            @Override
            public double calculate(double total) {
                double m1 = 100;
                double m2 = 49 * 0.8;
                double m3 = 151 * 0.5;
                double m4 = total - 300;
                return m1 + m2 + m3 + m4;
            }
        };

        private int min;
        private int max;
        private String graterThanSymbol;
        private String lessThanSymbol;
        private static ScriptEngineManager manager = new ScriptEngineManager();
        private static ScriptEngine engine = manager.getEngineByName("js");
        private static Map<String, Train> map = new HashMap<>();

        public static double calculateTotal(double total) throws ScriptException {
            engine.put("total", total);
            for (Map.Entry<String, Train> entry : map.entrySet()) {
                if (engine.eval(entry.getKey()) == Boolean.TRUE) {
                    return entry.getValue().calculate(total);
                }
            }
            return total;
        }

        static {
            for (Train train : Train.values()) {
                map.put("total" + train.graterThanSymbol + train.min + " && " + "total" + train.lessThanSymbol + train.max, train);
            }
        }

        Train(int min, String graterThanSymbol, int max, String lessThanSymbol) {
            this.min = min;
            this.lessThanSymbol = lessThanSymbol;
            this.max = max;
            this.graterThanSymbol = graterThanSymbol;
        }

        public abstract double calculate(double total);
    }

2.根据题目中的描述将方法写出来

private double money(int num) throws ScriptException {
        if (num <= 0) {
            return 0;
        }
        int total = 6 * num;
        return Train.calculateTotal(total);
    }

3.执行方法查看结果

@Test
    public void testTrain() {
        int num = 40;
        DecimalFormat df = new DecimalFormat("#.00");
        try {
            System.out.println(df.format(money(num)));
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }

总结:通过上面的修改,可以很清晰自己的代码逻辑,维护起来也更加的容易。

posted @ 2020-08-31 14:41  灬毛毛  阅读(208)  评论(0编辑  收藏  举报