• 工厂模式的实际运用


    工厂模式

    开发中,有时会需要根据不同的类型,创建同一接口的对应的不同实现类,再去执行方法。
    工厂模式的理解,详情见: 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);
            }
        }
    
    }
    
  • 相关阅读:
    Hadoop入门进阶课程12--Flume介绍、安装与应用案例
    Hadoop入门进阶课程11--Sqoop介绍、安装与操作
    Hadoop入门进阶课程10--HBase介绍、安装与应用案例
    Hadoop入门进阶课程9--Mahout介绍、安装与应用案例
    Hadoop入门进阶课程8--Hive介绍和安装部署
    Hadoop入门进阶课程7--Pig介绍、安装与应用案例
    zookeeper启动失败,但是状态显示已启动的原因
    微信小程序企业给零钱打款 提示未配置api发起,请查看产品中心企业付款配置
    java利用反射交换两个对象中的字段相同的字段值
    centos上 小程序部署 nginx+https+ssL 提示错误:对应的服务器 TLS 为 TLS 1.0 ,小程序要求的 TLS 版本必须大于等于 1.2
  • 原文地址:https://www.cnblogs.com/expiator/p/16633666.html
Copyright © 2020-2023  润新知