工厂模式的实际运用

工厂模式

开发中,有时会需要根据不同的类型,创建同一接口的对应的不同实现类,再去执行方法。
工厂模式的理解,详情见: https://www.cnblogs.com/expiator/p/8245143.html

示例

以下会举一个例子,不同的反馈类型 type,创建不同的审批处理器对象,进行审批。

自定义注解

/**
 * 审批的注解
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Audit {

    /**
     * 类型
     *
     */
    String[] types();

    /**
     * 名称
     *
     */
    String name() default "";

}

基础接口

不同的类型type,会有不同的处理器去处理。
各个审批处理器的对象,需要实现 AuditHandler 接口。

/**
 * 审批处理器接口
 */
public interface AuditHandler {

    /**
     * 审批
     * @param id
     * @param type
     * @return
     */
    void audit(Long id, String type);

}

实现接口的类1

/**
 * 审批处理器。
 * 通过注解指定处理哪些类型的提议
 *
 */
@Audit( types = {"1"}, name = "审批处理器-类型1")
@Component
@Slf4j
public class FirstAuditHandler  implements AuditHandler {

    @Override
    public void audit(Long id , String type) {
        log.info("FirstAuditHandler audit.id:{}, type:{}", id, type);
    }
}

实现接口的类2

/**
 * 审批处理器。
 * 通过注解指定处理哪些类型的提议
 *
 */
@Audit( types = {"2"}, name = "审批处理器-类型2")
@Component
@Slf4j
public class SecondAuditHandler implements AuditHandler {

    @Override
    public void audit(Long id, String type) {
        //忽略其他审批逻辑
        log.info("SecondAuditHandler audit.id:{}, type:{}", id, type);
    }

}

实现接口的类3

/**
 * 审批处理器。
 * 通过注解指定处理哪些类型的提议
 *
 */
@Audit( types = {"3","4","5"}, name = "审批处理器-公共")
@Component
@Slf4j
public class CommonAuditHandler implements AuditHandler {

    @Override
    public void audit(Long id, String type) {
        //忽略其他审批逻辑
        log.info("CommonAuditHandler audit.id:{}, type:{}", id, type);
    }


}

通过类型,获取对象

如果直接对比类型去获取对应的对象,在类型比较多的时候,会有大量的if else
通过map获取,可以减少if else判断。

/**
 * 审批的初始化 map,以及获取实例
 */
public class AuditContext {

    /**
     * 自动审批处理器
     */
    private static final Map<String, AuditHandler> AUTO_AUDIT_HANDLERS_MAP = new HashMap<>();


    private AuditContext() {
    }

    /**
     * 初始化 map
     *
     * @param types
     * @param name
     * @param auditHandler
     */
    public static void initMap(String[] types, String name, AuditHandler auditHandler) {
        for (String type : types) {
            AUTO_AUDIT_HANDLERS_MAP.put(type, auditHandler);
        }
    }

    /**
     * 通过类型,获取实例。
     * 如果直接对比类型,在类型比较多的时候,会有大量的if else
     * 通过map获取,可以减少if else判断。
     *
     * @param type
     * @return
     */
    public static AuditHandler getInstance(String type) {
        if (StringUtils.isBlank(type)) {
            return null;
        }
        return AUTO_AUDIT_HANDLERS_MAP.get(type);
    }

}

类型对应对象的Map初始化

/**
 * 初始化审批的处理器及实例的Map
 *
 */
@Component
@Slf4j
public class AuditInitService implements ApplicationContextAware, InitializingBean {

    private ApplicationContext context;

    @Override
    public void afterPropertiesSet()  {
        init();
    }

    /**
     * 设置上下文
     * @param applicationContext
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)  {
        this.context = applicationContext;
    }




    /**
     * 初始化审批的处理器及实例Map
     */
    private void init() {
        Map<String, Object> beans = context.getBeansWithAnnotation(Audit.class);
        Type[] genericInterfaces;
        Class<?> clazz;
        Type rawType;
        AuditHandler auditHandler;
        Audit audit;
        String[] types;
        String name;
        for (Object bean : beans.values()) {
            //getGenericInterfaces(): 主要是 获取由此对象表示的类或接口直接实现的接口的Type。
            genericInterfaces = bean.getClass().getGenericInterfaces();
            for (Type genericInterface : genericInterfaces) {
                if (Class.class.isAssignableFrom(genericInterface.getClass())) {
                    clazz = (Class<?>) genericInterface;
                    // isAssignableFrom() 用于检测一个类是否继承(或实现)于一个类/接口
                    if (AuditHandler.class.isAssignableFrom(clazz)) {
                        auditHandler = (AuditHandler) bean;
                        //获取AuditHandler实现类上面的@Audit注解
                        audit = auditHandler.getClass().getAnnotation(Audit.class);
                        types = audit.types();
                        name = audit.name();
                        //初始化审批的处理器及实例Map
                        AuditContext.initMap(types, name, auditHandler);
                        log.info(" Init auditHandler[{}] success!  The types is {}...", name, Arrays.toString(types));
                    }
                }
            }
        }
    }
}

根据类型创建对象

初始化map的作用体现出来了,不用做太多的if else判断去获取对象类型。

/**
 * 反馈提议
 */
@Service
public class SuggestionService {


    /**
     * 反馈提议后,进行审批
     */
    public void suggest(Long id ,String type) {
        //忽略其他的反馈逻辑
        //...
        //获取类型对应的审批处理器对象
        //初始化map的作用体现出来了,不用做太多的if else判断去获取对象类型
        AuditHandler auditHandler = AuditContext.getInstance(type);
        if (auditHandler != null) {
            //审批
            auditHandler.audit(id, type);
        }
    }

}

posted on   乐之者v  阅读(91)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2019-08-28 在error日志打印异常
2019-08-28 后端开发常用的工具/软件
2018-08-28 表单无法跳转
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示