<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一次代碼優(yōu)化實踐,用了模板方法+策略+工廠方法模式

          共 4433字,需瀏覽 9分鐘

           ·

          2020-10-06 02:17


          優(yōu)化代碼前

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

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

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

          ?

          ?

          優(yōu)化代碼思路

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

          模板方法模式

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

          既然每個Handler處理,都是類似的流程,那「定義一個抽象類,把查詢商戶信息,加簽,http請求,驗簽什么的,都放到里面去,儼然一個模板一樣」。然后,因為有些商戶走h(yuǎn)ttp代理,有些又沒走代理,怎么辦呢? 定義「一個抽象方法,給子類實現(xiàn)」嘛,因為能共用就放到父類(當(dāng)前的抽象類),不能共用就放到子類嘛~代碼如下:

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

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

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

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

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

          策略模式

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

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

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

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

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

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

          工廠方法模式

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

          在工廠模式中,我們在創(chuàng)建對象時不會對客戶端暴露創(chuàng)建邏輯,并且是通過使用一個共同的接口來指向新創(chuàng)建的對象。

          工廠方法模式具體實現(xiàn)就是:接口定義一個枚舉,每個服務(wù)實現(xiàn)都重新實現(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;
          ????}?

          來來來,工廠方法模式出爐咯:

          @Component
          public?class?CompanyServiceFactory?implements?ApplicationContextAware?{

          ????private?static?Map?map?=?new?HashMap<>();

          ????@Override
          ????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
          ????????Map?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è)計模式生搬硬套,而是優(yōu)化代碼過程中,發(fā)現(xiàn)這個設(shè)計模式剛好適用,才去用的哈。附上最后的代碼咯:

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


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

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


          好文章,我在看??

          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费无码做爱视频 | 久久免费学生妹 | 婷婷久久小说网 | 青草网络青 | 一级二级黄色视屏 |