一次程式碼優化實踐,用了模板方法+策略+工廠方法模式
前言
好久沒分享工作總結啦,今天來一份程式碼優化總結。用模板方法+策略+工廠方法模式優化了程式碼,耐心點看完,應該對大家有幫助的~
本文已經收錄到github
❝https://github.com/whx123/JavaHome
❞
「公眾號:撿田螺的小男孩」
優化程式碼前
先來了解一下類似的業務場景,簡言之,就是:多個商戶接入我們系統,都是走一個類似的流程通過http請求出去的。
優化前,每個公司對應一個控制代碼服務,虛擬碼如下:
//商戶A處理控制代碼
CompanyAHandlerimplementsRequestHandler{
Resphander(req){
//查詢商戶資訊
queryMerchantInfo();
//加簽
signature();
//http請求(走代理)
httpRequestbyProxy()
//驗籤
verify();
}
}
//商戶B處理控制代碼
CompanyBHandlerimplementsRequestHandler{
Resphander(Rreq){
//查詢商戶資訊
queryMerchantInfo();
//加簽
signature();
//http請求(不走代理)
httpRequestbyDirect();
//驗籤
verify();
}
}
//商戶C處理控制代碼
CompanyBHandlerimplementsRequestHandler{
Resphander(Rreq){
//查詢商戶資訊
queryMerchantInfo();
//webservice方式呼叫
requestByWebservice();
}
}
優化程式碼思路
我的優化程式碼思路,是有「重複程式碼,先把它抽出來,或者公用變數,或者公用方法,伸著公用類」。所以呢,查詢商戶資訊呀,加簽呀,http請求呀先全部各抽成一個公用方法。你細心點會發現,連每個Handler處理過程都很類似的,大概都是查詢商戶資訊+加簽+http請求+驗籤,於是呢,可以直接把它們抽象成一個公用類呀~在這裡就要引入模板方法模式咯
模板方法模式
在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但呼叫將以抽象類中定義的方式進行。
這種型別的設計模式屬於行為型模式。
既然每個Handler處理,都是類似的流程,那「定義一個抽象類,把查詢商戶資訊,加簽,http請求,驗籤什麼的,都放到裡面去,儼然一個模板一樣」
abstractclassAbstractCompanyCommonServiceimplementsICompanyCommonService{
//模板方法
ResphandlerTempPlate(req){
//查詢商戶資訊
queryMerchantInfo();
//加簽
signature();
//http請求
if(isRequestByProxy()){
httpProxy();
}else{
httpDirect();
}
//驗籤
verifySinature();
}
//Http是否走代理
abstractbooleanisRequestByProxy();
}
子類商戶A實現:
CompanyAServiceImplextendsAbstractCompanyCommonService{
Resphander(req){
returnhandlerTempPlate(req);
}
//公司A是走代理的
booleanisRequestByProxy(){
returntrue;
}
子類商戶B實現:
CompanyBServiceImplextendsAbstractCompanyCommonService{
Resphander(req){
returnhandlerTempPlate(req);
}
//公司B是不走代理的
booleanisRequestByProxy(){
returnfalse;
}
策略模式
心細的讀者會發現,甚至提出疑問,「你的商戶C的服務實現跟你定義的公用模板,不太一樣呢」,那當然,實際開發中,不跟你定義的模板一樣太常見了,需求是產品提的嘛,又不是根據你模板提的,是程式碼服務於需求的。好了,不多說啦,我使用了策略模式,來優化這個問題。
在策略模式(Strategy Pattern)中,一個類的行為或其演算法可以在執行時更改。這種型別的設計模式屬於行為型模式。
策略模式理解起來其好抽象對不對?我個人理解,其實策略模式就是定義一個方法(所謂演算法),給子類自己去實現。實際上就是「定義個方法/介面,讓子類自己去實現」。看程式碼吧:
//定義一個方法,把策略交給子類去實現。
interfaceICompanyCommonService{
Resphander(req);
}
前面商戶A和商戶B還是不變,使用抽象類AbstractCompanyCommonService的模板,模板不滿足商戶C,商戶C只能自己去實現咯,各個子類自己去實現的行為,就是策略模式的體現呢,如下:
CompanyCServiceImplextendsAbstractCompanyCommonService{
Reshander(req){
//查詢商戶資訊
queryMerchantInfo();
requestByWebservice();
}
//隨意了,你都不走模板了
booleanisRequestByProxy(){
returnfalse;
}
工廠方法模式
商戶A、B、C服務怎麼被管理呢,之前分別給A,B,C服務實現handler的,現在好了,都不知道怎麼管理了,怎麼知道呼叫哪個呢?別慌,解決方案是「工廠方法模式」。
在工廠模式中,我們在建立物件時不會對客戶端暴露建立邏輯,並且是通過使用一個共同的介面來指向新建立的物件。
工廠方法模式具體實現就是:介面定義一個列舉,每個服務實現都重新實現列舉,設定遊戲地圖唯一標誌列舉,再交給spring容器管理。看程式碼咯:
interfaceICompanyCommonService{
Resphander(req);
CompanyEnumgetCompanyEnum();
}
CompanyAServiceImplextendsAbstractCompanyCommonService{
Resphander(req){
returnhandlerTempPlate(req);
}
//公司A是走代理的
booleanisRequestByProxy(){
returntrue;
}
CompanyEnumgetCompanyEnum(){
returnCompanyEnum.A;
}
CompanyBServiceImplextendsAbstractCompanyCommonService{
Resphander(req){
returnhandlerTempPlate(req);
}
//公司B是不走代理的
booleanisRequestByProxy(){
returnfalse;
}
CompanyEnumgetCompanyEnum(){
returnCompanyEnum.B;
}
來來來,工廠方法模式出爐咯:
@Component
publicclassCompanyServiceFactoryimplementsApplicationContextAware{
privatestaticMap<CompanyEnum,ICompanyCommonService>map=newHashMap<>();
@Override
publicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{
Map<String,ICompanyCommonService>tempMap=applicationContext.getBeansOfType(ICompanyCommonService.class);
tempMap.values().forEach(iCompanyCommonService->
map.put(iCompanyCommonService.getCompanyEnum(),iCompanyCommonService));
}
publicResphandler(req){
returnmap.get(CompanyEnum.getCompanyEnum(req.getCompanyFlag()).hander(req);
}
}
最後建議
最後,不要為了使用設計模式生搬硬套,而是優化程式碼過程中,發現這個設計模式剛好適用,才去用的哈。附上最後的程式碼咯:
@Service
publicclassCompanyHandlerimplementsRequestHandler{
@Autowire
privateCompanyServiceFactorycompanyServiceFactory;
Resphander(req){
returncompanyServiceFactory.handler(req);
}
}
2020年10月22日~24日,由IT168旗下ITPUB企業社群平臺主辦的第十二屆中國系統架構師大會(SACC2020)將在雲端進行網路直播。自2009年以來,SACC架構師大會已成功舉辦了十一屆,雲集了國內CTO、研發總監、高階系統架構師、開發工程師和IT經理等技術人群,與會規模超千人。過去為期3天的議程,涉及20+專場,近120個主題,完整遷移到線上進行網路直播對會議。整裝待發,奮起逆襲的SACC2020,期待您的報名參與,共襄盛舉!