对switch进行拆分重构,降低复杂度,6种方式
如何对switch进行拆分重构
在我们编写代码的时候,常常遇到许多if-else或者switch的情况,这种情况下如果分支过多,会导致我们的最大复杂度过大,可能在公司编代码的时候通过不了检测,我们可以对这些分支提取成方法单独存在,也只是能降低平均圈复杂度,最大还是无济于事,所以这里我写了6种方式来降低复杂度:
1、利用多态,也就是方法重写
2、方法重写加反射
3、纯反射
4、利用枚举、重写方法
5、利用方法内部类重写接口或者抽象方法
6、Lambda表达式(基于函数的匿名表达式)同5一样,利用Lambda来简化了写法
这6中方式我个人认为枚举更好,也清晰,lambda也不错
如果谁有更好的方法,欢迎指正分享
先来看一下普通的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; 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、Lambda表达式(基于函数的匿名表达式)同5一样,利用Lambda来简化了写法
这种方式也就是利用了jdk8的新特性lambda来简化了内部类的写法,也就是new一个接口,实现接口具体方法的方式被简化了,但是要注意,接口里面只能有一个方法,这样利用箭头函数调用的时候,才会自动匹配到这个方法。这是lmbada的特性,箭头函数的括号里面可以写形参,参数名字可以不和接口形参的名字对应,但参数数量要和接口方法一一对应,在使用时,你传入的的值会按照顺序一一传入。例子:
public class Test4 { public static void main(String[] args) { getStudent().eat("苹果"); } public static Student getStudent() { return (footName) -> { System.out.println("学生吃了一个:" + footName); return footName; }; } public interface Student { public String eat(String foot); } }
下面你可以看到定义了个Case7接口,接口里面有一个print方法,这个方法根据情况随便写,名字、返回、形参等随意,现在这个print方法就是我们要调用的,map中的value全部为Case7类的对象,我们在添加map数据时,去实现这个方法的具体内容,然后通过map的key键获取到对应的Case7对象,执行print方法,就会对应的执行我们在往map中装入数据时具体去实现的内容。
下面这段代码是本次提取swith的代码:
import java.util.HashMap; import java.util.Map; public class Test4 { public static Map<String, Case7> caseMap5 = new HashMap<>(); static { caseMap5.put("1",()->{System.out.println("情况1");}); caseMap5.put("2",()->{System.out.println("情况2");}); caseMap5.put("3",()->{System.out.println("情况3");}); caseMap5.put("4",()->{System.out.println("情况4");}); caseMap5.put("5",()->{System.out.println("情况5");}); caseMap5.put("6",()->{System.out.println("情况6");}); } public static void main(String[] args) { String type = "4"; caseMap5.get(type).print(); } public interface Case7{ public void print(); } }
最终7种情况打印的结果一致:
————————————————
版权声明:本文为CSDN博主「IT_CREATE」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/IT_CREATE/article/details/107147765