最近完成了我們公司的公眾號開發,在微信消息路由選擇的時候一開始都是用if-else 來判斷,后面if-else月寫越多顯得十分的亂。在網上簡單查了一下解決方法,果然有不少干貨,感覺最經典最簡潔的還是使用策略模式來重構過多的if-else 選擇。
首先我們新建一個interface
public interface InnerCommand {
void process(String msg);
}
然后把每一個if邏輯都單獨抽取到一個類里面如
/** * @author lee. * @date 2019/5/24 15:53 */ @Service public class PrintAdminCommand implements InnerCommand { @Override public void process(String msg) { System.out.println("PrintAdminCommand"); } }
這里就不一一列舉了。
然后我們這里新建一個enum CommonCode
/** * @author lee. * @date 2019/5/24 15:51 */ public enum CommonCode { USER("user", "用戶", "com.yumstone.invoiceapply.Command.impl.PrintUserCommand"), ADMIN("admin", "管理員", "com.yumstone.invoiceapply.Command.impl.PrintAdminCommand"); private String code; private String desc; private String clazz; private static final Map<String, String> classes = new HashMap<String, String>(); static { for (CommonCode refer : CommonCode.values()) { classes.put(refer.getCode(), refer.getClazz()); } } CommonCode(String code, String desc, String clazz) { this.code = code; this.desc = desc; this.clazz = clazz; } public static Map<String, String> getAllClazz() { return classes; } public static String getDescByCode(int code) { return classes.get(code); } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getClazz() { return clazz; } public void setClazz(String clazz) { this.clazz = clazz; } }
這里我們可以看到枚舉類里面有一個靜態代碼塊在程序一開始執行的的時候就會把類和對應的code 加載到內存中。
再然后我們新建一個組件處理根據不同的code獲取不同的處理類,
/** * @author lee. * @date 2019/5/24 15:59 */ @Component public class InnerCommandContext { @Autowired ApplicationContext applicationContext; public InnerCommand getInstance(String command) { //getAllClazz Map<String, String> allClazz = CommonCode.getAllClazz(); String clazz = allClazz.get(command); InnerCommand innerCommand = null; try { if (clazz==null||clazz.length()==0) { clazz = PrintAdminCommand.class.getName() ; } innerCommand = (InnerCommand)applicationContext.getBean(Class.forName(clazz)); } catch (Exception e) { e.printStackTrace(); } return innerCommand; } }
這里我們可以看到獲取的類是通過反射在spring容器里面找到的。好了到這里我們的准備工作就做完了最后寫我們的邏輯部分。
/** * @author lee. * @date 2019/5/24 16:06 */ @RestController public class TextController { @Autowired InnerCommandContext innerCommandContext; @RequestMapping("text") public String test(@RequestParam String name){ InnerCommand innerCommand = innerCommandContext.getInstance(name); innerCommand.process(name); return "ok" ; } }
是不是特別簡潔 原來可能很多if-else 的判斷現在被優化成了兩行代碼
InnerCommand innerCommand = innerCommandContext.getInstance(name); innerCommand.process(name);
總結程序在啟動的時候會把所有的邏輯類的類名加載到內存中,然后通過code找到所需的類型通過反射構建出來,最后就可以執行所需要處理的業務了,在新增一個邏輯只需要新增一個
InnerCommand 的實現類並且添加到枚舉類里面去就行了。然后就可以通過該類型的code來獲取。
