(寫在最前:還沒入門的搬磚工的一本正經的胡說八道)
引言: 最近做到的項目中,需要給對接方提供一個公共接口,根據對方傳入的XML文件的rootelement分發調用接口,最簡單的使用if-else if 模式,但是看着實在太蠢。
場景一:需要根據關鍵字,進行接口分發
使用if-else模式缺點:
- 看着蠢
- 不易閱讀(個人觀點)
- 不易維護
- balabala...不想編了,就是看着不爽
如果只有一兩個方法還好,如果方法多了,額。。。如下,自行體會。
1 public class TestMethod { 2 3 public Object dispatchMethod(String name, String data) { 4 Object obj = null; 5 6 if ("methodA".equal(name)) { 7 obj = methodA(data); 8 } else if ("methodB".equal(name)) { 9 obj = methodB(data); 10 } else if (...) { 11 ... 12 } 13 return obj; 14 } 15 16 private Object methodA(String data) { 17 ... 18 } 19 20 private Object methodB(String data) { 21 ... 22 } 23 24 ... 25 }
那么步入正題,我才用的反射模式,匹配目標方法,我認為可以降低維護和閱讀成本
開發環境:jdk1.8
實現代碼:
- 定義目標方法枚舉,包含rootelement信息,調用方法說明,目標方法targetName
1 public enum MethodEnum { 2 3 METHODA("MethodA","調用方法A","methodA"), 4 METHODB("MethodB","調用方法B","methodB"), 5 ; 6 7 @Getter 8 private String code; //rootelement 9 10 @Getter 11 private String message; 12 13 @Getter 14 private String name; //目標方法名 15 16 private MethodEnum (String code,String message,String name) { 17 this.code = code; 18 this.message = message; 19 this.name = name; 20 } 21 22 public static MethodEnum fromCode(String code) { //根據傳入code,篩選目標方法 23 for (DockingFliggyHotelEnum p : DockingFliggyHotelEnum.values()) { 24 if(p.code.equalsIgnoreCase(code)) { 25 return p; 26 } 27 } 28 return null; 29 } 32 }
- 定義反射方法工具類
1 /** 2 * 定義工具類 3 **/ 4 public class MethodUtil { 5 6 public static Method getTargetMethod(Class clazz, String methodName) { 7 Method[] methods = clazz.getDeclaredMethods(); //獲取所有方法,包含private 8 if (methods != null && methods.length > 0) { 9 String regEx = "^" + methodName +"$";//獲取所要查找到的方法名稱要匹配此正則 10 Pattern pattern = Pattern.compile(regEx); 11 for (Method method : methods) { 12 Matcher matcher = pattern.matcher(method.getName()); 13 boolean rs = matcher.find(); 14 if(rs){ 15 return method; 16 } 17 } 18 } 19 return null; 20 } 21 22 public static Object executeTargrtMethod(Class clazz, String methodName, String xmlData) { 23 Object obj = null; 24 try { 25 Method method = getTargetMethod(clazz, methodName); 26 obj = method.invoke(clazz, xmlData); 27 } catch (Exception e) { 28 29 } 30 return obj; 31 } 32 33 }
- 具體分發
1 public class TestDispatch { 2 3 public Object dispatch(String root, String xml) { 4 String name = MethodEnum.fromCode(root).name; 5 Object obj = executeTargrtMethod(this.getClass(), name, xml) 6 return obj; 7 } 8 9 private Object methodA(String xml) { 10 Object obj = null; 11 ... 12 return obj; 13 } 14 15 private Object methodB(String xml) { 16 Object obj = null; 17 ... 18 return obj; 19 } 20 21 ... 22 }
對於業務代碼結構清晰明了,是不是看着爽多了。
對於類似的場景很多,都可以使用反射機制。
場景二:項目中多處需要大批量插入數據,提取一個公共方法,減少代碼行數,何樂而不為呢?
對了,順便說一下這個批量插入方法,數據庫使用mysql,項目框架springboot,jdk1.8,5000條數據插入一次,耗時0.8s左右。
1 /** 2 * @param batchCount 一次批量插入數據量 3 * @param target 目標方法關鍵字 4 * @param list 需要插入的大批量數據 5 * @throws Exception 6 */ 7 public static void batchInsert(Class clazz, int batchCount, String target, List<?> list) throws Exception{ 8 Method method = getTargetMethod(target); 9 int batchLastIndex = batchCount - 1;//每批最后一個的下標 10 for(int index = 0; index < list.size()-1;){ 11 if(batchLastIndex > list.size()-1){ 12 batchLastIndex = list.size() - 1; 13 if (method != null) { 14 method.invoke(clazz,list.subList(index, batchLastIndex)); 15 } 16 break;//數據插入完畢,退出循環 17 }else{ 18 if (method != null) { 19 method.invoke(clazz,list.subList(index, batchLastIndex)); 20 } 21 index = batchLastIndex + 1;//設置下一批下標 22 batchLastIndex = index + (batchCount - 1); 23 } 24 } 25 }
實驗結束,代碼分析下次在寫了。
寫在最后
代碼是偽代碼,可能啥地方寫得不對,歡迎指正
對於以上兩種場景,我目前只能想到這種方法。。。如果你有更好的,歡迎來懟我