美文网首页
没有难看的if-else的简单工厂实现

没有难看的if-else的简单工厂实现

作者: n油炸小朋友 | 来源:发表于2020-11-27 16:16 被阅读0次

    一、前言

    最近接到一个任务,需要从NSQ消息队列获取业务数据,类型依靠message(16进制数)的前四位判断,判断完数据类型,再根据类型以不同的方式处理这些数据。目前推送过来的消息只有一部分类型是需要做处理的,后续还会增加其他类型的处理。

    由于数据类型不单一而且要支持扩展,所以想要利用工厂设计模式,通过工厂返回可以处理该类型数据的处理类实例。可是工厂模式里面需要靠if-else做类型判断,十分丑陋,并且扩展新类型时带有侵入性,所以想了一种方法,让数据类型的枚举拥有能返回对应类型的处理器实例,这样枚举就同时能用拥有判断类型和返回对应类型处理器的功能,然后在工厂类中由这个枚举去动态地返回处理类实例,解决了问题。

    二、实现

    1. 工厂:
    @Component
    public class MiYueDataProcessorFactory {
    
        // 数据类型字段长度
        private static final Integer PREX_LENGTH = 4;
    
        public ProcessorBase getBy(byte[] msg) {
    
            if (msg == null || msg.length <= 0) {
                return null;
            }
    
            // 转换成16进制
            String msgStr = StringTool.byteArray2HexString(msg);
    
            if (StringUtils.isNotBlank(msgStr) && msgStr.length() >= PREX_LENGTH) {
                String prex = msgStr.substring(0, PREX_LENGTH);
                if (StringUtils.isNotBlank(prex)) {
                    // 获取枚举
                    MiYueDataTypeEnum miYueDataTypeEnum = MiYueDataTypeEnum.get(prex);
                    if (miYueDataTypeEnum != null) {
                        // 返回处理类
                        return miYueDataTypeEnum.returnProcessor();
                    }
                }
            }
            return null;
        }
    }
    
    1. 处理类抽象接口 以及 处理类
      处理器接口:
    public interface ProcessorBase {
        // 处理数据
        void process(byte[] data);
    }
    
    

    某个处理器实现类:

    @Component
    public class AttendanceProcessor implements ProcessorBase {
    
        public static AttendanceProcessor attendanceProcessor;
    
        @Autowired
        private ApplicationContext applicationContext;
    
        @PostConstruct
        public void init() {
            // 注入静态的属性
            attendanceProcessor = (AttendanceProcessor) applicationContext.getBean("attendanceProcessor");
        }
    
    
        @Override
        public void process(byte[] data) {
            // TODO
        }
    
    
    }
    
    1. 枚举以及接口
      该接口返回一个数据处理类
    public interface MiYueDataTypeProcessorReturner {
        ProcessorBase returnProcessor();
    }
    

    枚举:

    @Getter
    @AllArgsConstructor
    public enum MiYueDataTypeEnum implements MiYueDataTypeProcessorReturner {
    
    
        ATTENDANCE("1234", "考勤") {
            @Override
            public ProcessorBase returnProcessor() {
                return AttendanceProcessor.attendanceProcessor;
            }
        };
    
        private static final Map<String, MiYueDataTypeEnum> ENUM_VALUE_MAP = Maps.newHashMap();
    
        static {
            for (MiYueDataTypeEnum typEnum : MiYueDataTypeEnum.values()) {
                ENUM_VALUE_MAP.put(typEnum.getPrex(), typEnum);
            }
        }
    
        private String prex;
        private String reasonPhrase;
    
        public static MiYueDataTypeEnum get(String prex) {
            if (StringUtils.isBlank(prex)) {
                return null;
            }
            return ENUM_VALUE_MAP.get(prex);
        }
    
    }
    

    4.使用

    @Component
    @Slf4j
    public class NsqMsgDeal implements NSQMessageCallback {
    
        @Autowired
        private MiYueDataProcessorFactory factory;
    
        @Override
        public void message(NSQMessage nsqMessage) {
            try {
                // 获取处理类
                ProcessorBase processor = factory.getBy(nsqMessage.getMessage());
                if (processor != null) {
                    // 处理数据
                    processor.process(nsqMessage.getMessage());
                }
            } catch (Exception e) {
                // 数据处理异常处理。。。
            } finally {
                nsqMessage.finished();
            }
        }
    }
    

    新增新类型

    只需增加枚举类型以及处理器实现。

    相关文章

      网友评论

          本文标题:没有难看的if-else的简单工厂实现

          本文链接:https://www.haomeiwen.com/subject/zcbxwktx.html