坐地铁打折问题
前言:昨天一个初学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();
}
}
总结:通过上面的修改,可以很清晰自己的代码逻辑,维护起来也更加的容易。