摘要:此案例中,門面類為,然后各個門面方法的參數均為抽象類,通過決定調用中的哪個子類。抽象類持有類的對象,并且實現累的一個接口是為了容器啟動完成的時候自動把相應的校驗器加入到校驗器鏈中。
引言:很久沒有更新了,主要是工作忙。最近,工作中一個子系統升級,把之前不易擴展的缺點給改進了一下,主要是運用了幾個設計模式進行稍微改造了一下。1.項目背景
本文也同步發布至簡書,地址: https://www.jianshu.com/p/962...
在公司的一個實際項目中,需要做一個第三方公司(以下簡稱GMG)的系統集成工作,把該公司的一些訂單數據集成到自己公司平臺下,各個訂單具有一些共性,但是也有其特有的特征。 經過設計,目前我把訂單分為POLICY和BOB類型(暫且這么說吧,反正就是一種訂單類型,大家參照著看就OK)。
在訂單數據集成到公司平臺前,需要對訂單數據進行一些必要的業務邏輯校驗操作,并且每個訂單都有自己的校驗邏輯(包含公共的校驗邏輯)。 本節介紹的便是整個訂單集成系統中的校驗邏輯在綜合利用設計模式的基礎上進行架構設計。
2.校驗邏輯本校驗邏輯主要分為四個部分:
校驗文件名稱(RequestValidator.validateFileInfo)
校驗文件內容中的概要部分(RequestValidator.validateSummary)
校驗文件內容中的列名稱(RequestValidator.validateHeaders)
校驗文件內容中的明細(RequestValidator.validateDetails)
其實上面的RequestValidator的實現邏輯最后都是委托給RequestValidationFacade這個門面類進行相應的校驗操作。
3.實現細節 3.1 domain介紹主要分為RequestFile和RequestDetail兩個domain,RequestFile接收泛型的類型(即RequestFile), 使得其子類能夠自動識別相應的RequestDetail的子類。RequestFile為抽象類,定義了以下抽象方法,由子類實現:
//由子類實現具體的獲取文件明細內容 public abstract ListgetRequestDetails(); //由子類實現具體的獲取workflow的值 public abstract WorkflowEnum getProcessWorkFlow(); //由子類實現文件列字段名列表 public abstract String[] getDetailHeaders();
RequestDetail及其子類就是workflow對應文件的明細內容。
3.2 WorkflowEnum枚舉策略本例中如下規定:
workflow為WorkflowEnum.POLICY對應文件名為:csync_policy_yyyyMMdd_HHmmss_count.txt
workflow為WorkflowEnum.BOB對應文件名為:csync_bob_integration_yyyyMMdd_HHmmss_count.txt
以上校驗邏輯在AbstractRequestValidation類相應的子類中實現(validateFileName方法),其實這個枚舉貫穿整個校驗組件,它就是一個針對每個業務流程定義的一個枚舉策略。
3.3 涉及到的設計模式實現思路 3.3.1 門面模式在客戶端調用程序中,采用門面模式進行統一的入口(門面模式講究的是脫離具體的業務邏輯代碼)。門面模式封裝的結果就是避免高層模塊深入子系統內部,同時提供系統的高內聚、低耦合的特性。
此案例中,門面類為RequestValidationFacade,然后各個門面方法的參數均為抽象類RequestFile,通過RequestFile->getProcessWorkFlow()決定調用AbstractRequestValidation中的哪個子類。 AbstractRequestValidation類構造方法中定義了如下邏輯:
requestValidationHandlerMap.put(this.accessWorkflow(),this.accessBeanName());
把子類中Spring自動注入的實體bean緩存到requestValidationHandlerMap中,key即為WorkflowEnum枚舉值,value為spring bean name, 然后在門面類中可以通過對應的枚舉值取得BeanName,進而得到AbstractRequestValidation相應的子類對象,進行相應的校驗操作。
注:這邊動態調用到AbstractRequestValidation相應的子類對象,其實也是隱藏著【策略模式】的影子。
類圖如下:
在具體的校驗邏輯中,用到核心設計模式便是模版方法模式,AbstractRequestValidation抽象類中定義了以下抽象方法:
/** * validate the file details * @param errMsg * @param requestFile * @return */ protected abstract StringBuilder validateFileDetails(StringBuilder errMsg,RequestFile requestFile); /** * validate the file name * @param fileName * @return */ protected abstract String validateFileName(String fileName); /** * return the current CSYNC_UPDATE_WORKFLOW.UPDATE_WORKFLOW_ID * @return */ protected abstract WorkflowEnum accessWorkflow(); /** * return the current file name"s format ,such as: csync_policy_yyyyMMdd_HHmmss_count.txt * @return */ protected abstract String accessFileNameFormat(); /** * return the subclass"s spring bean name * @return */ protected abstract String accessBeanName();
以上抽象方法就類似我們常說的鉤子函數,由子類實現即可。類圖如下圖所示:
在AbstractRequestValidation抽象類中有個抽象方法validateFileDetails,校驗的是文件的明細內容中的相應業務規則,此為核心校驗, 較為復雜,而且針對每個業務流程,其校驗邏輯相差較大,在此處,利用了責任鏈模式進行處理。
Validator為校驗器的父接口,包含兩個泛型參數(即:
String doValidate(R detail, F file, ValidatorChain chain) throws BusinessValidationException;
該方法含有一個ValidatorChain參數,就自然而然的為該校驗器形成一個鏈條提供便利條件。
ValidatorChain為校驗器鏈,含有兩個接口方法:
String doValidate(T requestDetail, F requestFile) throws BusinessValidationException; ValidatorChain addValidator(Validator validator, WorkflowEnum workflowId);
該處有一個addValidator方法,為ValidatorChain對象添加校驗器的方法,返回本身。對應于每個業務流程需要哪些校驗器就在此實現即可(即AbstractRequestValidation的子類方法validateFileDetails)。
類圖如下圖所示:
如果單單從上面的校驗器實現上來看,如果需要增加一個校驗器,就需要在AbstractRequestValidation的子類方法validateFileDetails中添加,然后進行相應的校驗操作。這樣就會非常的麻煩,沒有做到真正的解耦。 此時,策略模式就發揮到了可以動態選擇某種校驗策略的作用(Validator的實現類就是一個具體的校驗策略)。
AbstractValidatorHandler抽象類持有FileDetailValidatorChain類的對象,并且實現累Spring的一個接口ApplicationListener(是為了Spring容器啟動完成的時候自動把相應的校驗器加入到校驗器鏈中)。 核心就是WorkflowEnum這個策略枚舉的作用,在子類可以動態的取得相應的校驗器對象。
根據子類提供需要的校驗器所在的包名列表和不需要的校驗器列表,動態配置出需要的校驗器鏈表。核心實現邏輯如下:
private void addValidators() { List> validators = getValidators(); validators.forEach((validator) -> { String simpleName = validator.getSimpleName(); String beanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1); LOGGER.info("Added validator:{},spring bean name is:{}",simpleName,beanName); Validator validatorInstance = ApplicationUtil.getApplicationContext().getBean(beanName,validator); fileDetailValidatorChain.addValidator(validatorInstance,getWorkflowId()); }); }
具體實現可以參考github代碼即可。
該類含有以下幾個抽象方法:
protected abstract WorkflowEnum getWorkflowId(); /** * the package need to be added the validators * @return */ protected abstract SetgetBasePackages(); /** * the classes need to be excluded * @return */ protected abstract Set excludeClasses();
事例代碼地址:https://github.com/landy8530/...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74532.html
摘要:注解方式優點使用注解方式可以極大的減少使用模版方法模式帶來的擴展時需要繼承模版類的弊端,工廠注解的方式可以無需關心其他業務類的實現,而且減少了類膨脹的風險。 在上一篇文章Java設計模式綜合運用(門面+模版方法+責任鏈+策略)中,筆者寫了一篇門面模式、模版方法、責任鏈跟策略模式的綜合運用的事例文章,但是后來筆者發現,在實現策略模式的實現上,發現了一個弊端:那就是如果在后續業務發展中,需...
摘要:責任鏈模式的具體運用以及原理請參見筆者責任鏈模式改進方式引入適配器模式關于接口適配器模式原理以及使用場景請參見筆者適配器模式。 1 責任鏈模式現存缺點 由于責任鏈大多數都是不純的情況,本案例中,只要校驗失敗就直接返回,不繼續處理接下去責任鏈中的其他校驗邏輯了,故而出現如果某個部分邏輯是要由多個校驗器組成一個整理的校驗邏輯的話,則此責任鏈模式則顯現出了它的不足之處了。(責任鏈模式的具體運...
摘要:當然,除了讓我們顯得更加專業之外,在自己所學習或者工作的項目中,適當合理的使用設計模式,能夠給項目帶來很大的好處。 簡單說兩句 本文首發公眾號【一名打字員】 對不住各位老鐵了,年前說好要更幾波JAVA的東西,又偷懶了,沒辦法,在這里用小錘錘偷偷錘了自己幾下。由于工作原因,更新時間不定,各位老鐵有問題可以私聊我哈。 對于初學者或者是正在向中高級的Java程序猿(打字員)來說,時刻梳理自己...
摘要:能夠協調調用者和被調用者,能夠在一定程度上降低系統的耦合性。特點低耦合性,獨立性好,安全性應用客戶訪問不到或者被訪問者希望隱藏自己,所以通過代理來訪問自己。 我們接著上面的幾種模式繼續講: 4、組合模式 將對象組合成樹形結構表示部分-整體的層次結構。 特點:靈活性強 應用:對象的部分-整體的層次結構,模糊組合對象和簡單對象處理問題 代碼實現 /** 組合模式* *///繼承模式clas...
摘要:抽象工廠模式是為了處理對象具有等級結構以及對象族的問題。單例設計模式單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例,這個類成為單例類。 導語:設計模式是無數碼農前人在實際的生產項目中經過不斷的踩坑、爬坑、修坑的經歷總結出來的經驗教訓,經過抽象之后表達成的概念。能夠幫助后來的設計者避免重復同樣的錯誤或者彎路。我也抽空整理了一下設計模式,用自己的話總結了一下,自認...
閱讀 888·2021-09-22 15:17
閱讀 1916·2021-09-22 15:06
閱讀 2211·2021-09-08 09:35
閱讀 5098·2021-09-01 11:43
閱讀 3475·2019-08-30 15:55
閱讀 2150·2019-08-30 12:48
閱讀 3149·2019-08-30 12:45
閱讀 1782·2019-08-29 17:31