Spring框架与变形抽象工厂模式结合实践(m*n服务设计方法)

本文介绍了如何在Spring框架中应用变形抽象工厂模式来设计m*n服务。面对多个厂商和多种产品,通过外观模式和工厂模式组合,实现对外统一接口并利用Spring的IOC特性动态获取服务实现。文章详细阐述了设计背景、考虑因素、实现措施,并提供了代码示例,探讨了后续扩展的可能性,包括非Spring环境下的实现方案和SPI扩展方式。
摘要由CSDN通过智能技术生成

抽象工厂模式

抽象工厂模式

背景

(根据生产环境虚拟)目前又M个厂商,每个厂商又有N个产品,现在需要获取不同厂商的不同产品的详细信息(可以理解为级联查询获取详细信息)

考虑

  1. 使用if-else或switch-case方案
  2. 单个文件代码过长,
  3. 不同产品需要的配置信息类(class对象)相同但又不是同一个配置信息类,会出现很多全类名对象的代码
  4. 工厂方法
    1. 没有共同父类,返回Object对象还需要再进行instanceof判断,两边需要同时修改,麻烦

思考

  1. 先写一个对外统一暴露接口(IGeneralService),所有对外服务都通过该接口查询(外观模式?)
  2. IGeneralService接口根据不同厂商获取对应服务(IProviderService)(工厂模式?)
  3. IProviderService接口根据不同产品获取对应服务(IProductService)(工厂模式?)

措施

  1. 外观模式肯定是需要的,避免外层调用的麻烦

  2. 是否直接使用工厂模式

    1. 不同厂商、产品对外提供的服务都是一样的,即各自有一个共同父接口
    2. 需要考虑后续扩展。

    最开始是考虑使用工厂模式的,理由是简单,写起来比较快,缺点就是扩展时需要改工厂类。

    注意:前面说过使用的是Spring框架,Spring框架的两大特点之一就是IOC,容器中存储了bean对象。

    那么我们就可以考虑如何通过IOC容器获取到我们对应的bean对象了,即使用接口和bean名称获取实际服务实现类,一种变相抽象工厂(算是吧?)

代码实现

  • 为了查找服务及提供对外级联查询接口,准备注解类(通过查询注解即可知道有多少厂商和产品)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Provider {
   
    /**
     * 厂商名称,前端页面展示信息
     * @return
     */
    @AliasFor("label")
    String name() default "";
    /**
     * 厂商名称,前端页面展示信息
     * @return
     */
    @AliasFor("name")
    String label() default "";
    /**
     * 厂商值,前后端传递字段
     * @return
     */
    String value();
    /**
     * 厂商值,前后端传递字段
     * @return
     */
    String value();
    /**
     * 用于排序,根据实际情况考虑
     * @return
     */
    int order() default 0;
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Product {
   
    /**
     * 产品名称,用于页面展示
     * @return
     */
    @AliasFor("label")
    String name() default "";
    /**
     * 产品名称,用于页面展示
     * @return
     */
    @AliasFor("name")
    String label() default "";
    /**
     * 产品值,用于前后端查询
     * @return
     */
    String value();
    /**
     * 用于排序,根据实际情况考虑
     * @return
     */
    int order() default 0;
}
  • 需要一个容器工具类,用于获取bean对象
public class SpringUtil implements ApplicationContextAware {
   

    private static ApplicationContext applicationContext = null;

    private static final Logger logger = LoggerFactory.getLogger(SpringUtil.class);
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
   

        if (SpringUtil.applicationContext == null) {
   
            SpringUtil.applicationContext = applicationContext;
        }
    }
    /**
     * 获取applicationContext
     */
    public static ApplicationContext getApplicationContext
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值