日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

一次代码优化实践,用了模板方法+策略+工厂方法模式

發(fā)布時(shí)間:2025/3/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一次代码优化实践,用了模板方法+策略+工厂方法模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

優(yōu)化代碼前

先來(lái)了解一下類似的業(yè)務(wù)場(chǎng)景,簡(jiǎn)言之,就是:多個(gè)商戶接入我們系統(tǒng),都是走一個(gè)類似的流程通過(guò)http請(qǐng)求出去的。

優(yōu)化前,每個(gè)公司對(duì)應(yīng)一個(gè)句柄服務(wù),偽代碼如下:

//?商戶A處理句柄 CompanyAHandler?implements?RequestHandler?{Resp?hander(req){//查詢商戶信息queryMerchantInfo();//加簽signature();//?http請(qǐng)求(走代理)httpRequestbyProxy()//?驗(yàn)簽verify();} } //?商戶B處理句柄 CompanyBHandler?implements?RequestHandler?{Resp?hander(Rreq){//查詢商戶信息queryMerchantInfo();//加簽signature();//?http請(qǐng)求(不走代理)httpRequestbyDirect();//?驗(yàn)簽verify();?} } //?商戶C處理句柄 CompanyBHandler?implements?RequestHandler?{Resp?hander(Rreq){//查詢商戶信息queryMerchantInfo();//?webservice?方式調(diào)用requestByWebservice();} }

?

?

優(yōu)化代碼思路

我的優(yōu)化代碼思路,是有「重復(fù)代碼,先把它抽出來(lái),或者公用變量,或者公用方法,伸著公用類」。所以呢,查詢商戶信息呀,加簽呀,http請(qǐng)求呀先全部各抽成一個(gè)公用方法。你細(xì)心點(diǎn)會(huì)發(fā)現(xiàn),連每個(gè)Handler處理過(guò)程都很類似的,大概都是查詢商戶信息+加簽+http請(qǐng)求+驗(yàn)簽,于是呢,可以直接把它們抽象成一個(gè)公用類呀~在這里就要引入模板方法模式咯

模板方法模式

在模板模式(Template Pattern)中,一個(gè)抽象類公開(kāi)定義了執(zhí)行它的方法的方式/模板。它的子類可以按需要重寫(xiě)方法實(shí)現(xiàn),但調(diào)用將以抽象類中定義的方式進(jìn)行。 這種類型的設(shè)計(jì)模式屬于行為型模式。

既然每個(gè)Handler處理,都是類似的流程,那「定義一個(gè)抽象類,把查詢商戶信息,加簽,http請(qǐng)求,驗(yàn)簽什么的,都放到里面去,儼然一個(gè)模板一樣」。然后,因?yàn)橛行┥虘糇遠(yuǎn)ttp代理,有些又沒(méi)走代理,怎么辦呢? 定義「一個(gè)抽象方法,給子類實(shí)現(xiàn)」嘛,因?yàn)槟芄灿镁头诺礁割?#xff08;當(dāng)前的抽象類),不能共用就放到子類嘛~代碼如下:

abstract?class?AbstractCompanyCommonService?implements?ICompanyCommonService?{?//模板方法Resp?handlerTempPlate(req){//查詢商戶信息queryMerchantInfo();//?加簽signature();//http?請(qǐng)求if(isRequestByProxy()){httpProxy();}else{httpDirect();}//?驗(yàn)簽verifySinature();}//?Http是否走代理abstract?boolean?isRequestByProxy(); }

子類商戶A實(shí)現(xiàn):

CompanyAServiceImpl?extends?AbstractCompanyCommonService{Resp?hander(req){return?handlerTempPlate(req);}//公司A是走代理的boolean?isRequestByProxy(){return?true;}

子類商戶B實(shí)現(xiàn):

CompanyBServiceImpl?extends?AbstractCompanyCommonService{Resp?hander(req){return?handlerTempPlate(req);}//公司B是不走代理的boolean?isRequestByProxy(){return?false;}

策略模式

心細(xì)的讀者會(huì)發(fā)現(xiàn),甚至提出疑問(wèn),「你的商戶C的服務(wù)實(shí)現(xiàn)跟你定義的公用模板,不太一樣呢」,那當(dāng)然,實(shí)際開(kāi)發(fā)中,不跟你定義的模板一樣太常見(jiàn)了,需求是產(chǎn)品提的嘛,又不是根據(jù)你模板提的,是代碼服務(wù)于需求的。好了,不多說(shuō)啦,我使用了策略模式,來(lái)優(yōu)化這個(gè)問(wèn)題。

在策略模式(Strategy Pattern)中,一個(gè)類的行為或其算法可以在運(yùn)行時(shí)更改。這種類型的設(shè)計(jì)模式屬于行為型模式。

策略模式理解起來(lái)其好抽象對(duì)不對(duì)?我個(gè)人理解,其實(shí)策略模式就是定義一個(gè)方法(所謂算法),給子類自己去實(shí)現(xiàn)。實(shí)際上就是「定義個(gè)方法/接口,讓子類自己去實(shí)現(xiàn)」??创a吧:

//?定義一個(gè)方法,把策略交給子類去實(shí)現(xiàn)。 interface?ICompanyCommonService{Resp?hander(req); }

前面商戶A和商戶B還是不變,使用抽象類AbstractCompanyCommonService的模板,模板不滿足商戶C,商戶C只能自己去實(shí)現(xiàn)咯,各個(gè)子類自己去實(shí)現(xiàn)的行為,就是策略模式的體現(xiàn)呢,如下:

CompanyCServiceImpl?extends?AbstractCompanyCommonService{Res?hander(req){//查詢商戶信息queryMerchantInfo();requestByWebservice();????}//隨意了,你都不走模板了boolean?isRequestByProxy(){return?false;}

工廠方法模式

商戶A、B、C服務(wù)怎么被管理呢,之前分別給A,B,C服務(wù)實(shí)現(xiàn)handler的,現(xiàn)在好了,都不知道怎么管理了,怎么知道調(diào)用哪個(gè)呢?別慌,解決方案是「工廠方法模式」。

在工廠模式中,我們?cè)趧?chuàng)建對(duì)象時(shí)不會(huì)對(duì)客戶端暴露創(chuàng)建邏輯,并且是通過(guò)使用一個(gè)共同的接口來(lái)指向新創(chuàng)建的對(duì)象。

工廠方法模式具體實(shí)現(xiàn)就是:接口定義一個(gè)枚舉,每個(gè)服務(wù)實(shí)現(xiàn)都重新實(shí)現(xiàn)枚舉,設(shè)置唯一標(biāo)志枚舉,再交給spring容器管理??创a咯:

interface?ICompanyCommonService{Resp?hander(req);CompanyEnum?getCompanyEnum(); }CompanyAServiceImpl?extends?AbstractCompanyCommonService{Resp?hander(req){return?handlerTempPlate(req);}//公司A是走代理的boolean?isRequestByProxy(){return?true;}CompanyEnum?getCompanyEnum(){return?CompanyEnum.A;}?CompanyBServiceImpl?extends?AbstractCompanyCommonService{Resp?hander(req){return?handlerTempPlate(req);}//公司B是不走代理的boolean?isRequestByProxy(){return?false;}CompanyEnum?getCompanyEnum(){return?CompanyEnum.B;}?

來(lái)來(lái)來(lái),工廠方法模式出爐咯:

@Component public?class?CompanyServiceFactory?implements?ApplicationContextAware?{private?static?Map<CompanyEnum,?ICompanyCommonService>?map?=?new?HashMap<>();@Overridepublic?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{Map<String,?ICompanyCommonService>?tempMap?=?applicationContext.getBeansOfType(ICompanyCommonService.class);tempMap.values().forEach(iCompanyCommonService?->map.put(iCompanyCommonService.getCompanyEnum(),?iCompanyCommonService));}public?Resp?handler(req)?{return?map.get(CompanyEnum.getCompanyEnum(req.getCompanyFlag()).hander(req);} }

?

?

最后建議

最后,不要為了使用設(shè)計(jì)模式生搬硬套,而是優(yōu)化代碼過(guò)程中,發(fā)現(xiàn)這個(gè)設(shè)計(jì)模式剛好適用,才去用的哈。附上最后的代碼咯:

@Service public?class?CompanyHandler?implements?RequestHandler??{@Autowireprivate?CompanyServiceFactory?companyServiceFactory;Resp?hander(req){return?companyServiceFactory.handler(req);} }

有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

歡迎大家關(guān)注Java之道公眾號(hào)

好文章,我在看??

總結(jié)

以上是生活随笔為你收集整理的一次代码优化实践,用了模板方法+策略+工厂方法模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。