最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中優(yōu)雅的編寫服務(wù)工廠的方法示例

 更新時(shí)間:2025年08月08日 10:54:15   作者:磊磊落落  
在基于 pringBoot的業(yè)務(wù)開發(fā)中,我們有時(shí)會(huì)遇到這樣的場(chǎng)景:即定義了一個(gè)通用接口,而該接口擁有多個(gè)實(shí)現(xiàn)類,在調(diào)用這些實(shí)現(xiàn)類時(shí),我們通常需要編寫一個(gè)工廠方法,下面就拉介紹一下如何實(shí)現(xiàn)

在基于 Spring Boot 的業(yè)務(wù)開發(fā)中,我們有時(shí)會(huì)遇到這樣的場(chǎng)景:即定義了一個(gè)通用接口,而該接口擁有多個(gè)實(shí)現(xiàn)類。在調(diào)用這些實(shí)現(xiàn)類時(shí),我們通常需要編寫一個(gè)工廠方法,該工廠方法可以根據(jù)指定的參數(shù)獲取到對(duì)應(yīng)的實(shí)現(xiàn)類。

那么,提供該工廠方法的類就是一個(gè)服務(wù)工廠,本文即是探討如何優(yōu)雅的編寫這個(gè)服務(wù)工廠。

1 場(chǎng)景描述

為了將所描述的場(chǎng)景具像化,下面舉一個(gè)易于理解的例子:「假定我們正在使用 Spring Boot 做一個(gè)對(duì)接多個(gè)第三方支付平臺(tái)的支付服務(wù)。」

我們?cè)趯?shí)現(xiàn)這個(gè)支付服務(wù)時(shí),定義了一個(gè)通用的支付接口 PaymentService,其擁有一個(gè) pay() 方法。該接口可以對(duì)訂單(Order)進(jìn)行支付,支付后會(huì)得到一個(gè)支付結(jié)果 PaymentResult

public interface PaymentService {
    PaymentResult pay(Order order);
}

public class Order {
}

public class PaymentResult {
    private boolean success;
    private String message;
}

目前這個(gè)支付服務(wù)需要支持三種支付類型:Alibaba、WeChat 和銀聯(lián)。

public enum PaymentType {
    ALIBABA,
    WECHAT,
    UNION
}

那么 PaymentService 就會(huì)擁有三個(gè)不同的實(shí)現(xiàn)類:AlibabaPaymentServiceImpl、WechatPaymentServiceImplUnionPaymentServiceImpl。

@Service("alibabaPaymentService")
public class AlibabaPaymentServiceImpl implements PaymentService {
    @Override
    public PaymentResult pay(Order order) {
        return ...;
    }
}

@Service("wechatPaymentService")
public class WechatPaymentServiceImpl implements PaymentService {
    @Override
    public PaymentResult pay(Order order) {
        return ...;
    }
}

@Service("unionPaymentService")
public class UnionPaymentServiceImpl implements PaymentService {
    @Override
    public PaymentResult pay(Order order) {
        return ...;
    }
}

為了方便調(diào)用,我們需要編寫一個(gè)工廠類 PaymentFactory,其能夠提供一個(gè)方法:可以根據(jù)不同的支付類型(PaymentType)獲取到 PaymentService 的具體實(shí)現(xiàn)。

public class PaymentFactory {

    public PaymentService getService(PaymentType paymentType) {
        return xxx;
    }
}

這樣調(diào)用者需要使用某種方式進(jìn)行支付時(shí),只需要指定支付類型,通過工廠類拿到 PaymentService,然后調(diào)用 pay() 方法就可以了。

PaymentService paymentService = paymentFactory.getService(PaymentType.WECHAT);
PaymentResult paymentResult = paymentService.pay(new Order());

System.out.println(paymentResult);

2 PaymentFactory 基礎(chǔ)實(shí)現(xiàn)

那么如何編寫這個(gè) PaymentFactory 呢?一種最基礎(chǔ)的寫法就是在 PaymentFactory 中將 PaymentService 所有的實(shí)現(xiàn)類都以屬性的方式注入進(jìn)來,然后在 getService() 方法中使用 if-elseswitch 語句根據(jù) PaymentType 來返回不同的實(shí)現(xiàn)類。

@Component
public class PaymentFactory {

    @Qualifier("alibabaPaymentService")
    @Autowired
    private PaymentService alibabaPaymentService;

    @Qualifier("wechatPaymentService")
    @Autowired
    private PaymentService wechatPaymentService;

    @Qualifier("unionPaymentService")
    @Autowired
    private PaymentService unionPaymentService;

    public PaymentService getService(PaymentType paymentType) {
        return switch (paymentType) {
            case ALIBABA -> alibabaPaymentService;
            case WECHAT -> wechatPaymentService;
            case UNION -> unionPaymentService;
            default -> throw new IllegalArgumentException("PaymentType is not supported");
        };
    }
}

這種寫法能用,但代碼行數(shù)有點(diǎn)多且有點(diǎn)笨拙,有沒有更高級(jí)一點(diǎn)的寫法呢?

3 PaymentFactory 高級(jí)實(shí)現(xiàn)

PaymentFactory 稍微高級(jí)一點(diǎn)的寫法是不用將實(shí)現(xiàn)類一一聲明為屬性,且不使用上述諸如 if-elseswitch 等條件判斷語句來根據(jù)不同參數(shù)返回不同的實(shí)現(xiàn)。

而是聲明一個(gè)存放 PaymentType 和實(shí)現(xiàn)類的 Map,然后在構(gòu)造方法中將實(shí)現(xiàn)類注入為方法參數(shù),然后建立該 Map,這樣在 getService() 方法中只需根據(jù) PaymentTypeMap 中直接獲取實(shí)現(xiàn)類即可。

@Component
public class PaymentFactory {

    private final Map<PaymentType, PaymentService> paymentServices;

    @Autowired
    public PaymentFactory(
            @Qualifier("alibabaPaymentService") PaymentService alibabaPaymentService,
            @Qualifier("wechatPaymentService") PaymentService wechatPaymentService,
            @Qualifier("unionPaymentService") PaymentService unionPaymentService) {
        paymentServices = Map.of(
                PaymentType.ALIBABA, alibabaPaymentService,
                PaymentType.WECHAT, wechatPaymentService,
                PaymentType.UNION, unionPaymentService
        );
    }

    public PaymentService getService(PaymentType paymentType) {
        return Optional.ofNullable(paymentServices.get(paymentType))
                .orElseThrow(() -> new IllegalArgumentException("PaymentType is not supported"));
    }
}

上面的實(shí)現(xiàn)比較優(yōu)雅,但代碼行數(shù)仍有點(diǎn)多,有沒有更簡(jiǎn)便的寫法呢?

有。因?yàn)?PaymentService 的實(shí)現(xiàn)類命名是有規(guī)則的,所以更簡(jiǎn)便的寫法即是借助 Spring BeanFactory 直接根據(jù) Bean 名稱獲取對(duì)應(yīng)的實(shí)現(xiàn)。

@Component
public class PaymentFactory {

    @Autowired
    private BeanFactory beanFactory;

    public PaymentService getService(PaymentType paymentType) {
        String beanName = paymentType.name().toLowerCase() + "PaymentService";
        if (!beanFactory.containsBean(beanName)) {
            throw new IllegalArgumentException("PaymentType is not supported");
        }
        return (PaymentService) beanFactory.getBean(beanName);
    }
}

上述代碼的確簡(jiǎn)潔了不少,但其與前面的寫法均有一個(gè)同樣的問題,即類上均含有 @Component 注解,即均需要交給 Spring 實(shí)例化。在靜態(tài)方法或由 Java 反射實(shí)例化的類中無法直接使用。

下面就嘗試編寫一個(gè)純靜態(tài)的 PaymentFactory,使得調(diào)用者可以直接像下面這樣通過 PaymentFactory.getService() 的方式獲取 PaymentService 的實(shí)現(xiàn)類。

PaymentService paymentService = PaymentFactory.getService(PaymentType.WECHAT);

這樣就需要依賴一個(gè)保存 Spring 應(yīng)用上下文的工具類了:

@Component
public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return context.getBean(beanName, clazz);
    }
}

SpringContextHolder 工具類可以在 Spring 加載完成后自動(dòng)持有 Spring 的 ApplicationContext。然后在后期有需要時(shí),調(diào)用者可以使用一個(gè)純靜態(tài)方法來獲取任意 Spring 管理的 Bean。

這樣,有了 SpringContextHolder 工具類后,我們的靜態(tài) PaymentFactory 就可以像下面這樣實(shí)現(xiàn)了。

public class PaymentFactory {

    public static PaymentService getService(PaymentType paymentType) {
        String beanName = paymentType.name().toLowerCase() + "PaymentService";
        return SpringContextHolder.getBean(beanName, PaymentService.class);
    }
}

4 小結(jié)

綜上,本文提出了如何在 Spring Boot 中編寫一個(gè)服務(wù)工廠的問題。然后針對(duì)該問題,舉了一個(gè)支付業(yè)務(wù)的例子,然后探索了 PaymentFactory 的基本寫法和更高級(jí)的寫法。以備有需要的同學(xué)在實(shí)際開發(fā)中做參考。

到此這篇關(guān)于SpringBoot中優(yōu)雅的編寫服務(wù)工廠的方法示例的文章就介紹到這了,更多相關(guān)SpringBoot服務(wù)工廠內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java靜態(tài)代理與動(dòng)態(tài)代理案例詳解

    Java靜態(tài)代理與動(dòng)態(tài)代理案例詳解

    這篇文章主要介紹了Java靜態(tài)代理與動(dòng)態(tài)代理案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Spring配置shiro時(shí)自定義Realm中屬性無法使用注解注入的解決辦法

    Spring配置shiro時(shí)自定義Realm中屬性無法使用注解注入的解決辦法

    今天小編就為大家分享一篇關(guān)于Spring配置shiro時(shí)自定義Realm中屬性無法使用注解注入的解決辦法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解

    Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法之二分查找詳解,二分查找算法是一種在有序數(shù)組中查找某一特定元素的搜索算法,其思想就是不斷地將有序查找表“一分為二”,逐漸縮小搜索區(qū)域,進(jìn)而找到目標(biāo)元素,需要的朋友可以參考下
    2023-12-12
  • springboot集成dubbo過程詳解

    springboot集成dubbo過程詳解

    本文詳細(xì)介紹了Spring Boot集成Dubbo的過程,包括多個(gè)BeanPostProcessor和初始化器的作用,以及ClassPathBeanDefinitionScanner和DubboClassPathBeanDefinitionScanner的使用方法
    2025-11-11
  • 最新評(píng)論

    苍溪县| 泰兴市| 揭东县| 区。| 久治县| 赣州市| 武威市| 双城市| 北宁市| 利辛县| 万盛区| 都江堰市| 香河县| 苍溪县| 通江县| 黄平县| 福贡县| 留坝县| 凤山市| 盐池县| 苍溪县| 龙井市| 尚志市| 华阴市| 江口县| 洪湖市| 五大连池市| 石景山区| 乐都县| 文山县| 鹤山市| 方山县| 阆中市| 祁门县| 班玛县| 诏安县| 汤原县| 偃师市| 博乐市| 宣恩县| 家居|