一大堆的if else 或 switch怎么办?
记得刚毕业实习时,参加公司的代码走查大会,那场景陌生难忘,大家都把这个会称为“一群程序员把一个程序员按在地上摩擦”。其中我印象最深刻的就是有一次看到一个同事的代码被展示在投影屏上,好家伙满满一屏的if...else if...else...,不仅及其影响代码美观,还影响程序性能,当时确实让我们这些在场的小小实习生无不感叹电商业务的复杂。大家吐槽归吐槽,但这种问题怎么解决,就一点一个吞吞吐吐说不清。后来有一个人果断站起来,这种情况最好用Map来代替!
为什么会存在大量if else或switch情况
这种情况通常存在电商业务前线,例如一个订单需要在不同的业务模式下进行处理,但是业务模式多达10种以上。这时候就会存在大量的if else判断该如何处理这个订单,有些朋友可能会觉得switch会比if else好一些,所以用switch代替,下面是一个简单的示例:
private void dealOrder(String orderType) {
if ("type1".equals(orderType)) {
// do something...
} else if ("type2".equals(orderType)) {
// do something...
} else if ("type3".equals(orderType)) {
// do something...
} else if ("type4".equals(orderType)) {
// do something...
} else if ("type5".equals(orderType)) {
// do something...
// ...else if ...
} else {
// do something..
}
}
// 或者这样
private void dealOrder(String orderType) {
switch (orderType) {
case "type1":
//do something
return;
case "type2":
// do something
return;
case "type3":
// do something
return;
case "type4":
// do something
return;
case "type5":
// do something
return;
default:
// do something
}
}
Map怎么代替呢?
其实在一些比较简单的情况下,就直接用Map代替就好了,例如我们判断完后处理的逻辑很简单,就获取一个字符串什么的。那么就直接事先用Map把这些不同type需要返回的字符串存起来,到时候直接取就可以了。
private static final Map<String, String> MAP = new HashMap<>(5);
static {
MAP.put("type1", "感谢你长这么帅还看我的文章");
MAP.put("type2", "感谢你长这么美还看我的文章");
MAP.put("type3", "感谢你长这么又帅又美还看我的文章");
MAP.put("type4", "感谢你长这么又帅又美又这么有富裕还看我的文章");
MAP.put("type5", "感谢你长这么又帅又美又这么有富裕还看我的文章,点个在看吧");
//...
}
public String doEasySomething(String type) {
return MAP.getOrDefault(type, "不知道你啥情况");
}
但是现实就是这么残酷,我们遇到往往并不是这么简单的场景。我前面提到的那位满屏if else的同事,代码里面的业务逻辑照样复杂,比如要去保存订单数据,要去更新商品库存、要去发送消息等等。这时候还有一些办法,就是在Map里去存一个具体的方法,像这样:
先声明一个这样的方法接口
public interface ConditionMethod<R> {
/**
* 需要执行的方法具体逻辑
*
* @return 执行结果
*/
R invoke();
}
然后前面的代码就可以变成这样了
private static final Map<String, ConditionMethod<String>> MAP = new HashMap<>(5);
static {
MAP.put("type1", () -> "感谢你长这么帅还看我的文章");
MAP.put("type2", () -> "感谢你长这么美还看我的文章");
MAP.put("type3", () -> "感谢你长这么又帅又美还看我的文章");
MAP.put("type4", () -> "感谢你长这么又帅又美又这么有富裕还看我的文章");
MAP.put("type5", () -> "感谢你长这么又帅又美又这么有富裕还看我的文章,点个在看吧");
}
public String doEasySomething(String type) {
return MAP.getOrDefault(type, () -> "不知道你啥情况").invoke();
}
当然这种情况也会存在一个问题,当方法里的具体逻辑很复杂的时候,我们map的put方法同样会变得特别难看,而且复杂。这时候其实可以结合“工厂模式”使用。先创建一个adapter的接口,在创建不同业务逻辑的adapter实现adapter接口,这样在map就可以返回adapter了,这里就不赘述了。
终极封装
上面的代码是否还会有优化的空间?答案当然是有的,Map存数据的这块逻辑其实还是可以优化的。可以创建一个类来更加方便的取和存,由于代码有点多,所以放github上了,大家可以自行查看。
https://github.com/SmythAsen/buffalo/tree/master/src/main/java/com/asen/buffalo/function
当年的感叹
说实话,虽然实习时的“代码走查”我觉得挺好,特别对于一些体量比较小的公司,因为招的人实力多半是不如一线大厂的,这种情况下只有架构师级别的这些公司领导才能确保代码的质量,不然很多代码真是没法看。我一直觉得当时在那学到了很多东西,有很多经验都沿用至今,经常通过当年“代码走查”的步骤一步步review自己的代码。
respect!respect!respect!
项目源代码地址:https://github.com/SmythAsen/conditional-function
关注我的公众号,获取更多信息