<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>

          原來(lái)使用 Spring 實(shí)現(xiàn)策略模式可以這么簡(jiǎn)單!

          共 3253字,需瀏覽 7分鐘

           ·

          2020-09-27 06:39

          每天早上七點(diǎn)三十,準(zhǔn)時(shí)推送干貨

          Hello,大家好,我是鴨血粉絲~

          最近看同事的代碼時(shí)候,學(xué)到了個(gè)小技巧,在某些場(chǎng)景下非常挺有用的,這里分享一下給大家。

          Spring 中?@Autowired注解,大家應(yīng)該不會(huì)陌生,用過(guò) Spring 的肯定也離不開這個(gè)注解,通過(guò)這個(gè)注解可以幫我們自動(dòng)注入我們想要的 Bean。

          除了這個(gè)基本功能之外,@Autowired?還有更加強(qiáng)大的功能,還可以注入指定類型的數(shù)組,List/Set 集合,甚至還可以是 Map 對(duì)象。

          比如說(shuō)當(dāng)前應(yīng)用有一個(gè)支付接口?PayService,分別需要對(duì)接支付寶、微信支付、銀行卡,所以分別有三個(gè)不同實(shí)現(xiàn)類?AliPayService,WechatPayservice,BankCardPayService

          四個(gè)類的關(guān)系如下圖所示:

          如果此時(shí)我需要獲取當(dāng)前系統(tǒng)類所有?PayService?Bean,老的方式我們只能通過(guò)?BeanFactory或者?ApplicationContext 獲取。

          //?首先通過(guò)?getBeanNamesForType?獲取?PayService?類型所有的?Bean
          String[]?names?=?ctx.getBeanNamesForType(PayService.class);
          List?anotherPayService?=?Lists.newArrayList();
          for?(String?beanName?:?names)?{
          ????anotherPayService.add(ctx.getBean(beanName,?PayService.class));
          }
          //?或者通過(guò)?getBeansOfType?獲取所有?PayService?類型
          Map?beansOfType?=?ctx.getBeansOfType(PayService.class);
          for?(Map.Entry?entry?:?beansOfType.entrySet())?{
          ????anotherPayService.add(entry.getValue());
          }

          但是現(xiàn)在我們可以不用這么麻煩了,我們可以直接使用?@Autowired?注入?PayService?Bean 數(shù)組,或者?PayService?List/Set 集合,甚至,我們還可以注入?PayService?的 Map 集合。

          @Autowired
          List?payServices;

          @Autowired
          PayService[]?payServicesArray;

          知道了這個(gè)功能,當(dāng)我們需要使用 Spring 實(shí)現(xiàn)策略模式就非常簡(jiǎn)單。

          可能有的小伙伴不太了解策略模式,沒(méi)關(guān)系,這類阿粉介紹一個(gè)業(yè)務(wù)場(chǎng)景,通過(guò)這個(gè)場(chǎng)景給大家介紹一下策略模式。

          還是上面的例子,我們當(dāng)前系統(tǒng)需要對(duì)接微信支付、支付寶、以及銀行卡支付。

          當(dāng)接到這個(gè)需求,我們首先需要拿到相應(yīng)接口文檔,分析三者的共性。

          假設(shè)我們這里發(fā)現(xiàn),三者模式比較類似,只是部分傳參不一樣。

          所以我們根據(jù)三者的共性,抽象出一組公共的接口?PayService

          public?interface?PayService?{
          ????PayResult?epay(PayRequest?request);
          }

          然后分別實(shí)現(xiàn)三個(gè)實(shí)現(xiàn)類,都繼承這個(gè)接口。

          那么現(xiàn)在問(wèn)題來(lái)了,由于存在三個(gè)實(shí)現(xiàn)類,如何選擇具體的實(shí)現(xiàn)類?

          其實(shí)這個(gè)問(wèn)題很好解決,請(qǐng)求參數(shù)傳入一個(gè)唯一標(biāo)識(shí),然后我們根據(jù)標(biāo)識(shí)選擇相應(yīng)的實(shí)現(xiàn)類。

          比如說(shuō)我們?cè)谡?qǐng)求類?PayRequest?搞個(gè)?channelNo?字段,這個(gè)代表相應(yīng)支付渠道唯一標(biāo)識(shí),比如說(shuō)支付寶為:00000001,微信支付為?00000002,銀行卡支付為?00000003

          接著我們需要把唯一標(biāo)識(shí)與具體實(shí)現(xiàn)類一一映射起來(lái),剛好我們可以使用?Map?存儲(chǔ)這種映射關(guān)系。

          我們實(shí)現(xiàn)一個(gè)?RouteService,具體代碼邏輯如下:

          @Service
          public?class?RouteService?{

          ????@Autowired
          ????Map?payServiceMap;

          ????public?PayResult?epay(PayRequest?payRequest)?{
          ????????PayService?payService?=?payServiceMap.get(payRequest.getChannelNo());
          ????????return??payService.epay(payRequest);
          ????}

          }

          我們?cè)?RouteService?自動(dòng)注入?PayService?所有相關(guān) Bean,然后使用唯一標(biāo)識(shí)查找實(shí)現(xiàn)類。

          這樣我們對(duì)外就屏蔽了支付渠道的差異,其他服務(wù)類只要調(diào)用?RouteService?即可。

          但是這樣實(shí)現(xiàn)還是有點(diǎn)小問(wèn)題,由于我們唯一標(biāo)識(shí)為一串?dāng)?shù)字,如果像我們上面直接使用?@Autowired注入?Map,這就需要我們實(shí)現(xiàn)類的?Bean?名字為?00000001?這些。

          但是這樣命名不是很優(yōu)雅,這樣會(huì)讓后來(lái)同學(xué)很難看懂,不好維護(hù)。

          所以我們需要做個(gè)轉(zhuǎn)換,我們可以這么實(shí)現(xiàn)。

          首先我們改造一下?PayService?這個(gè)接口,增加一個(gè)方法,每個(gè)具體實(shí)現(xiàn)類通過(guò)這個(gè)方法返回其唯一標(biāo)識(shí)。

          public?interface?PayService?{

          ????PayResult?epay(PayRequest?request);

          ????String?channel();
          }

          具體舉個(gè)支付寶實(shí)現(xiàn)類的代碼,其他實(shí)現(xiàn)類實(shí)現(xiàn)類似。

          @Service("aliPayService")
          public?class?AliPayService?implements?PayService?{

          ????@Override
          ????public?PayResult?epay(PayRequest?request)?{
          ????????//?業(yè)務(wù)邏輯
          ????????return?new?PayResult();
          ????}
          ????@Override
          ????public?String?channel()?{
          ????????return?"00000001";
          ????}
          }

          最后我們改造一下?RouteService,具體邏輯如下:

          @Service
          public?class?RouteService?{

          ????@Autowired
          ????Set?payServiceSet;
          ????
          ????Map?payServiceMap;

          ????public?PayResult?epay(PayRequest?payRequest)?{
          ????????PayService?payService?=?payServiceMap.get(payRequest.getChannelNo());
          ????????return??payService.epay(payRequest);
          ????}

          ????@PostConstruct
          ????public?void?init()?{
          ????????for?(PayService?payService?:?payServiceSet)?{
          ????????????payServiceMap?=?new?HashMap<>();
          ????????????payServiceMap.put(payService.channel(),?payService);
          ????????}
          ????}
          }

          上面代碼首先通過(guò)自動(dòng)注入?PayService?一個(gè)集合,然后我們?cè)賹⑵滢D(zhuǎn)為一個(gè)?Map,這樣內(nèi)部存儲(chǔ)剛好是唯一標(biāo)識(shí)與實(shí)現(xiàn)類的映射了。

          好了,今天的小技巧就分享到這里,學(xué)到小伙伴,不妨點(diǎn)個(gè)贊吧。


          瀏覽 43
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  天天干天天操天天舔 | 五月丁香| 三级成人网址 | 日韩精品成人一区二区三区蜜桃 | 国产美女精品 |