1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        原來使用 Spring 實現(xiàn)策略模式可以這么簡單!

        共 3253字,需瀏覽 7分鐘

         ·

        2020-09-27 06:39

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

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

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

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

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

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

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

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

        //?首先通過?getBeanNamesForType?獲取?PayService?類型所有的?Bean
        String[]?names?=?ctx.getBeanNamesForType(PayService.class);
        List?anotherPayService?=?Lists.newArrayList();
        for?(String?beanName?:?names)?{
        ????anotherPayService.add(ctx.getBean(beanName,?PayService.class));
        }
        //?或者通過?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;

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

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

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

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

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

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

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

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

        那么現(xiàn)在問題來了,由于存在三個實現(xiàn)類,如何選擇具體的實現(xiàn)類?

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

        比如說我們在請求類?PayRequest?搞個?channelNo?字段,這個代表相應(yīng)支付渠道唯一標(biāo)識,比如說支付寶為:00000001,微信支付為?00000002,銀行卡支付為?00000003。

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

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

        @Service
        public?class?RouteService?{

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

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

        }

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

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

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

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

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

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

        public?interface?PayService?{

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

        ????String?channel();
        }

        具體舉個支付寶實現(xiàn)類的代碼,其他實現(xiàn)類實現(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);
        ????????}
        ????}
        }

        上面代碼首先通過自動注入?PayService?一個集合,然后我們再將其轉(zhuǎn)為一個?Map,這樣內(nèi)部存儲剛好是唯一標(biāo)識與實現(xiàn)類的映射了。

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


        瀏覽 43
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            韩日成人高清无码一区二区 | 黄色在线免费一级视频 | www国产av | 特级西西xXWWW无码 | 日韩毛片免费视频 | 91麻豆精品国产自产在线观看一区 | 刘亦菲一区二区三区免费看 | 黄片免费视频 | 久久一线| 日本午夜福利视频 |