- 策略模式解決if - else 的程式碼
業務場景:
外包企業的審批人需要審批打卡的場景;
審批人分為多種不同的級別,多種級別中具有方式相同但是內容不同的操作:審批。
原來場景:
有前端傳來審批人蔘數,使用if-else 來判斷該審批人的級別屬於哪一個級別,執行相應的審批方法。每一個審批方法寫在了業務類底,命名採用1級審批,2級審批---等等的命名方式來命名。
問題:if - else 邏輯複雜,不易閱讀,函式中審批能抽象的地方未抽象,
兩個核心問題:test測試非常麻煩,新增審批人員需要對程式碼進行修改,違背開閉原則。
解決過程:
-
抽象審批中的原子操作的程式碼,比如查詢對應級別所審批的同學名單。程式碼變得好看一些,但是任然未解決,if - else 和 多個 審批方法的實現。
-
嘗試策略模式
-
使用策略模式將每個級別的使用者抽象起來
-
package strategy; public class Main { public static void main(String[] args) { if (LevelEnum.LEVEL1.equals(1)) { SupervisorControl supervisorControl = new SupervisorControl(new Supervisor1()); supervisorControl.execute(1); } if (LevelEnum.LEVEL2.equals(2)) { SupervisorControl supervisorControl = new SupervisorControl(new Supervisor2()); supervisorControl.execute(2); } if (LevelEnum.LEVEL3.equals(3)) { SupervisorControl supervisorControl = new SupervisorControl(new Supervisor3()); supervisorControl.execute(3); } } }
package strategy; public enum LevelEnum { LEVEL1, LEVEL2, LEVEL3 }
package strategy; public interface Supervisor { void examine(int supervisorId); }
package strategy; public class Supervisor1 implements Supervisor { public void examine(int supervisorId) { System.out.println("去做一些和1級supervisor相關的工作"); } }
package strategy; public class Supervisor2 implements Supervisor { public void examine(int supervisorId) { System.out.println("去做一些和2級supervisor相關的工作"); } }
package strategy; public class Supervisor3 implements Supervisor { public void examine(int supervisorId) { System.out.println("去做一些和3級supervisor相關的工作"); } }
package strategy; public class SupervisorControl { Supervisor supervisor; public SupervisorControl(Supervisor supervisor) { this.supervisor = supervisor; } public void execute(int id) { supervisor.examine(id); } }
-
解決方法:
- 混合使用策略模式和反射來解決
package strategy;
public class Main {
public static void main(String[] args) {
// if (LevelEnum.LEVEL1.equals(1)) {
// SupervisorControl supervisorControl = new SupervisorControl(new Supervisor1());
// supervisorControl.execute(1);
// }
// if (LevelEnum.LEVEL2.equals(2)) {
// SupervisorControl supervisorControl = new SupervisorControl(new Supervisor2());
// supervisorControl.execute(2);
// }
// if (LevelEnum.LEVEL3.equals(3)) {
// SupervisorControl supervisorControl = new SupervisorControl(new Supervisor3());
// supervisorControl.execute(3);
// }
String packageName = Supervisor1.class.getPackage().getName();
String supervisorName = packageName + "." + "Supervisor" + "2";
try {
Class<?> clazz = Class.forName(supervisorName);
Supervisor supervisor = (Supervisor) clazz.newInstance();
supervisor.examine(1);
} catch (Exception e) {
System.out.println(e);
}
}
}
注意
class.forName() 需要傳入的格式是"包名.類名"。如果找不到包名則會報ClassNotFoundException
可以通過class.getPackage來獲取包名。
到此我們解決了if - else 很多的問題,並且解決了需要侵入程式碼修改的問題,如果新增supervisor的級別,只需要和前端達成一致,後臺繼續寫一個supervisor4物件即可。
為什麼解決了test難的問題
對於test來說,每一個If-else 都需要我們去驗證,這其實就是兩個test, if 一個 else一個,如果有很多if - else,想要保證高的test覆蓋率,就會非常頭痛。
然而我們用策略模式 和 反射來解決,只需要,對主邏輯一個test,每一個實現方法做一個test即可。
至此,所有問題都解決了,程式碼一片光明。