如何对switch进行拆分重构
在我们编写代码的时候,常常遇到许多if-else或者switch的情况,这种情况下如果分支过多,会导致我们的最大复杂度过大,可能在公司编代码的时候通过不了检测,我们可以对这些分支提取成方法单独存在,也只是能降低平均圈复杂度,最大还是无济于事,所以这里我写了5种方式来降低复杂度:
1、利用多态,也就是方法重写
2、方法重写加反射
3、纯反射
4、利用枚举、重写方法
5、利用方法内部内重写接口或者抽象方法
这5中方式我个人认为枚举更好,也清晰
如果谁有更好的方法,欢迎指正分享
先来看一下普通的switch语句:
public class Test4 {
public static void main(String[] args) {
String type = "4";
switch (type) {
case "1":
System.out.println("情况1");
break;
case "2":
System.out.println("情况2");
break;
case "3":
System.out.println("情况3");
break;
case "4":
System.out.println("情况4");
break;
case "5":
System.out.println("情况5");
break;
case "6":
System.out.println("情况6");
break;
default:
}
}
}
这是一个普通的switch语句块,这里我列举了6个分支,default忽略,假设是几十个,甚至更多呢?这种情况我们就一直加case吗?不停地加case会不停地破坏原来的代码,当复杂度上去了之后,维护起来也麻烦,眼睛都给你看晕。
1、利用多态,也就是方法重写
利用map和抽象类,或者是接口,对于每种不同的情况重写具体的方法实现,这样就降低了方法中的复杂度,我们如果要添加新的分支条件,只需要实现抽象类或者接口的子类,重写方法内容,在向map中添加进当前的新增子类,就可以实现分支条件的扩展,缺点是子类过多。
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static sun.misc.Version.print;
public class Test4 {
public static Map<String, Case> caseMap1 = new HashMap<>();
static {
caseMap1.put("1", new Case1());
caseMap1.put("2", new Case2());
caseMap1.put("3", new Case3());
caseMap1.put("4", new Case4());
caseMap1.put("5", new Case5());
caseMap1.put("6", new Case6());
}
public static void main(String[] args) {
String type = "4";
caseMap1.get(type).print();
}
public static abstract class Case {
public abstract void print();
}
public static class Case1 extends Case {
@Override
public void print() {
System.out.println("情况1");
}
}
public static class Case2 extends Case {
@Override
public void print() {
System.out.println("情况2");
}
}
public static class Case3 extends Case {
@Override
public void print() {
System.out.println("情况3");
}
}
public static class Case4 extends Case {
@Override
public void print() {
System.out.println("情况4");
}
}
public static class Case5 extends Case {
@Override
public void print() {
System.out.println("情况5");
}
}
public static class Case6 extends Case {
@Override
public void print() {
System.out.println("情况6");
}
}
}
2、方法重写加反射
其实这个和第一个本质上没有什么区别,区别就是这种方式,是在调用时才去构造相应的对象
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static sun.misc.Version.print;
public class Test4 {
public static Map<String, Class<? extends Case>> caseMap = new HashMap<>();
static {
caseMap.put("1", Case1.class);
caseMap.put("2", Case2.class);
caseMap.put("3", Case3.class);
caseMap.put("4", Case4.class);
caseMap.put("5", Case5.class);
caseMap.put("6", Case6.class);
}
public static void main(String[] args) {
String type = "4";
factory(type).ifPresent(Case::print);
}
public static Optional<Case> factory(String type) {
try {
return Optional.of(caseMap.get(type).newInstance());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
//exception
System.out.println("异常");
return Optional.empty();
}
}
public static abstract class Case {
public abstract void print();
}
public static class Case1 extends Case {
@Override
public void print() {
System.out.println("情况1");
}
}
public static class Case2 extends Case {
@Override
public void print() {
System.out.println("情况2");
}
}
public static class Case3 extends Case {
@Override
public void print() {
System.out.println("情况3");
}
}
public static class Case4 extends Case {
@Override
public void print() {
System.out.println("情况4");
}
}
public static class Case5 extends Case {
@Override
public void print() {
System.out.println("情况5");
}
}
public static class Case6 extends Case {
@Override
public void print() {
System.out.println("情况6");
}
}
}
3、纯反射
这种方式和前两种就有区别了,这种就是利用反射机制直接去执行方法
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static sun.misc.Version.print;
public class Test4 {
public static Map<String, Method> caseMap2 = new HashMap<>();
static {
try {
caseMap2.put("1", Test4.class.getMethod("case1"));
caseMap2.put("2", Test4.class.getMethod("case2"));
caseMap2.put("3", Test4.class.getMethod("case3"));
caseMap2.put("4", Test4.class.getMethod("case4"));
caseMap2.put("5", Test4.class.getMethod("case5"));
caseMap2.put("6", Test4.class.getMethod("case6"));
} catch (NoSuchMethodException e) {
e.printStackTrace();
System.out.println("异常");
}
}
public static void main(String[] args) {
String type = "4";
execute(type);
}
public static void execute(String type) {
if (caseMap2.get(type) != null) {
try {
caseMap2.get(type).invoke(Test4.class.newInstance());
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
//exception
e.printStackTrace();
System.out.println("异常");
}
}
}
public void case1() {
System.out.println("情况1");
}
public void case2() {
System.out.println("情况2");
}
public void case3() {
System.out.println("情况3");
}
public void case4() {
System.out.println("情况4");
}
public void case5() {
System.out.println("情况5");
}
public void case6() {
System.out.println("情况6");
}
}
4、利用枚举、重写方法
这种方式就是我们在枚举中定义一个抽象方法,对于每个不同的情况进行重写方法,大家平常用的最多的可能就是把枚举当做常量来使用,其实枚举也是有构造方法,也是存在变量,方法的,其实这完全就是个类嘛,只是它对于不同的情况需要直接先在枚举内部构造出来而已
package com.company;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static sun.misc.Version.print;
public class Test4 {
public static Map<String, CaseEnum> caseMap3 = new HashMap<>();
static {
caseMap3.put("1", CaseEnum.CASE1);
caseMap3.put("2", CaseEnum.CASE2);
caseMap3.put("3", CaseEnum.CASE3);
caseMap3.put("4", CaseEnum.CASE4);
caseMap3.put("5", CaseEnum.CASE5);
caseMap3.put("6", CaseEnum.CASE6);
}
public static void main(String[] args) {
String type = "4";
caseMap3.get(type).print();
}
public enum CaseEnum {
CASE1() {
@Override
public void print() {
System.out.println("情况1");
}
},
CASE2() {
@Override
public void print() {
System.out.println("情况2");
}
},
CASE3() {
@Override
public void print() {
System.out.println("情况3");
}
},
CASE4() {
@Override
public void print() {
System.out.println("情况4");
}
},
CASE5() {
@Override
public void print() {
System.out.println("情况5");
}
},
CASE6() {
@Override
public void print() {
System.out.println("情况6");
}
};
public abstract void print();
}
}
5、利用方法内部内重写接口
这种方式其实和单独每种情况去实现接口的子类异曲同工,只是这种情况省略了单独对父类的继承,而是针对每种不同的情况对对象进行方法重写,其实也相当于上面枚举的变种
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static sun.misc.Version.print;
public class Test4 {
public static Map<String, Case> caseMap4 = new HashMap<>();
static {
caseMap4.put("1", new Case() {
@Override
public void print() {
System.out.println("情况1");
}
});
caseMap4.put("2", new Case() {
@Override
public void print() {
System.out.println("情况2");
}
});
caseMap4.put("3", new Case() {
@Override
public void print() {
System.out.println("情况3");
}
});
caseMap4.put("4", new Case() {
@Override
public void print() {
System.out.println("情况4");
}
});
caseMap4.put("5", new Case() {
@Override
public void print() {
System.out.println("情况5");
}
});
caseMap4.put("6", new Case() {
@Override
public void print() {
System.out.println("情况6");
}
});
}
public static abstract class Case {
public abstract void print();
}
public static void main(String[] args) {
String type = "4";
caseMap4.get(type).print();
}
}
最终6种情况打印的结果一致: