標籤:java 反射
java反射之前接觸比較多,但僅技術方面思考的多;這次主要是從業務角度出發,思考java反射在業務模組設計中如何發揮更高效的作用,以提高生產率。
1.業務需求
要處理銀行回單票據,提取出付款人、收款人及對應銀行和商務資訊,每個銀行的格式都不統一。所以需要對各家銀行的格式進行預先處理,規整為標準格式後,交由後續模組處理。
這個預先處理格式化的設計有多種
2.方案選型
| 做法 |
適用情境 |
技能要求 |
| 在if..else中添加分支邏輯 |
適用於分支較少的情境,如只有2~4個 |
簡單 |
| 把分支邏輯提取為控制代碼,顯示註冊到控制代碼map或list中 |
實用於分支較多情境,但變化不大;否則若經常變動,註冊時容易漏掉 |
需要有一定的業務抽象和介面設計能力 |
| 把分支邏輯提取為控制代碼,通過反射自動註冊到map或list中 |
實用於分支較多情境,也滿足經常變動情境 |
抽象能力+java反射技術 |
| 註冊到list? |
分支判斷邏輯複雜,只能採用低效的遍曆判斷 |
|
| 還是註冊到map? |
分支判斷邏輯清晰,特別是存在關鍵詞區分 |
|
3.採用反射的技術方案
我們這個情境的特點:
- 分支判斷邏輯非常清晰,就是根據每家銀行的回單類型進行分支判斷。
- 並且不斷有新類型會增加進來。
所以採用下面做法
3.1.抽象Formater介面,通過Map管理所有介面
public static HashMap<String,Formater> formaterMap = new HashMap<String,Formater>(); public interface Formater { void format(Resource resource); }
3.2.通過java反射自動註冊
- 獲得所有實作類別(用到了Reflections,這是一個開源工程,在github上有源碼)
- 執行個體化(如果是內部類,要特別注意執行個體化方法,可參考使用new和反射產生java內部類的執行個體化對象)
- 註冊到map中
static { Reflections reflections = new Reflections("prepare");//包名,可以降低搜尋範圍 Set<Class<? extends Formater>> subTypes = reflections .getSubTypesOf(Formater.class); for (Class<? extends Formater> clazz : subTypes) { String typeName = clazz.getTypeName(); int idx = typeName.lastIndexOf("$");//內部類情境 int idx1 = typeName.lastIndexOf("."); if(idx<idx1)idx = idx1; String className = typeName.substring(idx+1);//提取類名,作為主鍵 try { formaterMap.put(className, clazz.newInstance()); } catch (Exception e) { e.printStackTrace(); } } }
3.3.應用模組調用簡潔
//對銀行回單進行預先處理Formater formater = PrepareModule.formaterMap.get(resource.getResourceType());if(formater != null) formater.format(resource);//do next....
3.4.擴充分支簡單且不會出錯
以後擴充也比較簡單,只需要增加新的方法實作類別即可,不必擔心漏掉註冊的問題。
static public class ChinaBankReceiptFormater implements Formater { @Override public void format(Resource resource) { //TODO } }
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
java反射的應用實踐