用反射和annotation消除“if else”语句
在项目过程中,出现了这么一段丑陋的“ifelse”代码,如下:
public List<BreadcrumbVO> getBreadCrumbList(){ …… if(A){ doA(); } else if (B){ doB(); } else if (C); doC(); } else if (D){ doD(); } else if (E){ DoE(); } …… }
可以看出,因为条件不同,在这段逻辑代码中出现了大量的“ifelse”语句,这种代码是明显不符合面向对象思想的,是必须要重构的!
这个问题可以用多态来解决!一般是用多态+ Factory模式来解决,具体思路就是:
1. 新建一个接口或者abstract类,定义一个abstract方法,交给子类实现
2. 将每一个if分支中的代码独立出来,作为步骤1中接口或者abstract类的子类,并实现其abstract方法,有多少个if分支,就有多少个子类
3. 新建一个Factory类,用于根据不同判断条件,生成不同子类
4. 在原逻辑方法中使用“父类引用指向子类实例(Factory生成)”。
这样业务逻辑比较清楚,可以不用管生成的子类实例具体是什么,代码可扩展性比较强。当有新的判断条件时,只需新增一个子类,并在Factory类中新增该类的生成代码即可。但是这种解决方案还存在一些问题:类太多,不方便维护和管理;“ifelse”依然存在,只是从业务逻辑中转移到Factory类而已
于是我想出了另外一个解决方案,可彻底消除”ifelse”语句,不管是在业务逻辑中还是在Factory类中。我的这种解决方案采用了 reflect + annotation + Factory, 具体思路就是:
1. 新建一个annotation类,用于替代“if”分支的判断条件
2. 新建一个Factory方法
3. 将原业务逻辑中if else分支中的代码剥离出来,在Factory类中创建对应的method(我的if else分支中的代码比较简单,要是复杂点的话,可以采用类来实现),在method上添加annotation
4. 在Factory中利用反射和annotation根据不同的条件调用相对应的处理函数
具体代码如下:
public String findString(){ String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId(); for (Method m : this.getClass().getDeclaredMethods()){ if (m.getAnnotation(MethodConditions.class) != null){ MethodConditions condition = m.getAnnotation(MethodConditions.class); if (parameters.get(condition.id()) != null && viewId.equalsIgnoreCase(condition.viewId())){ try {… } catch (Exception e) { } } } } … } @MethodConditions(id = "a", viewId = "/a/a.xhtml") private String doA(){ … } @MethodConditions(id = "b", viewId = "/b/b.xhtml") private String doB(){ … } @MethodConditions(id = "c", viewId = "/c/c.xhtml") private String doC(){ … } @MethodConditions(id = "d", viewId = "/d/d.xhtml") private String doD(){ … } @MethodConditions(id = "e", viewId = "/e/e.xhtml") private String doE(){ … } import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface MethodConditions { String id(); String viewId();}
页:
[1]