在项目过程中,出现了这么一段丑陋的“ if else”代码,如下:
public List<BreadcrumbVO> getBreadCrumbList(){ …… if(A){ doA(); } else if (B){ doB(); } else if (C); doC(); } else if (D){ doD(); } else if (E){ DoE(); } …… }
可以看出,因为条件不同,在这段逻辑代码中出现了大量的“ if else ”语句,这种代码是明显不符合面向对象思想的,是必须要重构的!
这个问题可以用多态来解决!一般是用多态 + Factory 模式来解决,具体思路就是:
1. 新建一个接口或者 abstract 类,定义一个 abstract 方法,交给子类实现
2. 将每一个 if 分支中的代码独立出来,作为步骤 1 中接口或者 abstract 类的子类,并实现其 abstract 方法,有多少个 if 分支,就有多少个子类
3. 新建一个 Factory 类,用于根据不同判断条件,生成不同子类
4. 在原逻辑方法中使用“父类引用指向子类实例( Factory 生成)”。
这样业务逻辑比较清楚,可以不用管生成的子类实例具体是什么,代码可扩展性比较强。当有新的判断条件时,只需新增一个子类,并在 Factory 类中新增该类的生成代码即可。但是这种解决方案还存在一些问题:类太多,不方便维护和管理;“ if else ”依然存在,只是从业务逻辑中转移到 Factory 类而已
于是我想出了另外一个解决方案,可彻底消除 ”if else” 语句,不管是在业务逻辑中还是在 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(); }