单例模式(Singleton Pattern) 和 工厂模式(Factory Pattern) 的结合

@Slf4j
@Component
public class ThirdChannelWaybillService {

    Map<String, ThirdChannelWaybillHandler> thirdChannelWaybillHandlerHashMap = new HashMap<>();

    private synchronized ThirdChannelWaybillHandler getProcessWaybillHandler(String thirdChannel){
        ThirdChannelWaybillHandler thirdChannelWaybillHandler = thirdChannelWaybillHandlerHashMap.get(thirdChannel);
        if (thirdChannelWaybillHandler == null){
            Map<String, ThirdChannelWaybillHandler> thirdChannelWaybillHandlerMap = ApplicationUtils.beanMap(ThirdChannelWaybillHandler.class);
            for (ThirdChannelWaybillHandler handler : thirdChannelWaybillHandlerMap.values()) {
                if (!thirdChannelWaybillHandlerHashMap.containsKey(handler.getThirdChannel())){
                    thirdChannelWaybillHandlerHashMap.put(handler.getThirdChannel(), handler);
                }
            }
        }
        return thirdChannelWaybillHandlerHashMap.get(thirdChannel);
    }


    public Response addWaybill(ThirdWaybillParam param){
        ThirdChannelWaybillHandler processWaybillHandler = this.getProcessWaybillHandler(param.getThirdChannelCode());
        return processWaybillHandler.addWaybill(param);
    }
}

1. 单例模式(Singleton Pattern)

getProcessWaybillHandler 方法中,使用了 synchronized 关键字确保方法线程安全,并且通过 thirdChannelWaybillHandlerHashMap 来缓存每个 thirdChannel 对应的 ThirdChannelWaybillHandler 实例。这种做法在一定程度上保证了对于每个 thirdChannel,该 ThirdChannelWaybillHandler 只会创建一次,并且在之后的调用中重用这个实例。可以认为这里是对 ThirdChannelWaybillHandler 对象的 单例模式 的一种变体,尤其是在多线程环境下。

具体分析:
  • thirdChannelWaybillHandlerHashMap.get(thirdChannel) 负责从缓存中获取对应的 ThirdChannelWaybillHandler
  • 如果缓存中没有相应的处理器 (thirdChannelWaybillHandler == null),则通过 ApplicationUtils.beanMap(ThirdChannelWaybillHandler.class) 加载所有的 ThirdChannelWaybillHandler 实例,并将其添加到缓存中 (thirdChannelWaybillHandlerHashMap.put(handler.getThirdChannel(), handler))。
  • 由于使用了 synchronized,此方法确保在多线程环境下,同一时刻只有一个线程可以加载 ThirdChannelWaybillHandler 实例,从而防止了重复加载和线程安全问题。

2. 工厂模式(Factory Pattern)

getProcessWaybillHandler 方法本质上是一个工厂方法,负责根据 thirdChannel 创建或返回相应的 ThirdChannelWaybillHandler 实例。虽然并不完全符合传统的工厂模式(因为没有显式的工厂类),但它的行为符合工厂模式的基本思想:根据某种条件(thirdChannel)动态返回不同的实例。

具体分析:
  • ApplicationUtils.beanMap(ThirdChannelWaybillHandler.class) 实际上是根据 ThirdChannelWaybillHandler 类型加载相关实例,这种方式与工厂模式中的实例化过程类似。
  • 然后通过 thirdChannelWaybillHandlerHashMap.put 将创建的实例缓存下来,以便后续调用。

 以下获取一个Map类型的Bean实例

Map<String, ThirdChannelWaybillHandler> thirdChannelWaybillHandlerMap = ApplicationUtils.beanMap(ThirdChannelWaybillHandler.class);
@Slf4j
@Component
public class ApplicationUtils implements ApplicationContextAware {

    private static final String NOT_EXIST_ERRMSG = "bean.not.exist";
    private static final String NOT_REPO_ERRMSG = "clazz.not.repository";
    private static final String NOT_SERVICE_ERRMSG = "clazz.not.service";
    @Setter
    private static ApplicationContext applicationContext;

    /**
     * 获取一个Bean实例
     *
     * @param clazz 目标Bean实例类型
     * @param <T>   目标Bean范型限制
     * @return Bean实例,如果Bean不存在,则抛出FrameworkException异常
     */
    public static <T> T bean(Class<T> clazz) {
        if (applicationContext == null) {
            throw new BusinessException(CommonExceptionCode.DEFAULT_ERROR.getErrCode(), NOT_EXIST_ERRMSG);
        }
        Map beans = applicationContext.getBeansOfType(clazz);
        T t = (T) beans.values().stream().findFirst().orElse(null);

        if (t == null) {
            throw new BusinessException(CommonExceptionCode.DEFAULT_ERROR.getErrCode(), NOT_EXIST_ERRMSG);
        }
        return t;
    }

  
    /**
     * 获取一个Map类型的Bean实例
     *
     * @param clazz 目标Bean实例类型
     * @param <T>   目标Bean范型限制
     * @return Bean实例,如果Bean不存在,则抛出FrameworkException异常
     */
    public static <T> Map<String, T> beanMap(Class<T> clazz) {
        if (applicationContext == null) {
            throw new BusinessException(CommonExceptionCode.DEFAULT_ERROR.getErrCode(), NOT_EXIST_ERRMSG);
        }
        Map<String, T> beans = applicationContext.getBeansOfType(clazz);

        if (beans == null) {
            throw new BusinessException(CommonExceptionCode.DEFAULT_ERROR.getErrCode(), NOT_EXIST_ERRMSG);
        }
        return beans;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (ApplicationUtils.applicationContext == null) {
            ApplicationUtils.applicationContext = applicationContext;
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值