工厂模式加策略模式 解决if太多报文解析问题

前提概要

** 本文介绍工厂加策略模式的设计模式 因为对设备操作解析报文的全量数据太多需要判断 所以以下对数据解析的 if-else采用了设计模式对代码简洁开发 耦合度更高 更加可观方便的新增代码**

前提例子对比

在这里插入图片描述
上图给个例子:一般我们对数据进行判断需要用到switch或者if-else进行判断 数据量大的话要写很多的判断 这样后续需要加新的判断就会变得很麻烦 而且代码的结构性会很大一段 看起来非常吃力后续维护也是非常麻烦,所以来看看运用了设计模式在项目的运用

项目结构

在这里插入图片描述

第一步定义一个枚举类

我这边采用枚举类来判断值,就是定义需要你在if里面需要等于的那个值 放在枚举类里面

package com.qykfa.enumtype;

import lombok.Getter;
import lombok.NoArgsConstructor;

/**
 * @author Administrator
 * @auther KeShuai
 * @Date: 2020/08/20/9:50
 * @Description:
 */
@Getter
@NoArgsConstructor
public enum AlarmType {
    /**
     * 终止流程
     */
    ChangeAlarmJud("02008001"),
    /**
     * 故障
     */
    failure("01002001"),
    /**
     * 告警
     */
    GiveAnAlarm("01003001"),
    /**
     * 烟雾
     */
    SmokeAlarm("02017001"),
    /**
     * 浸水
     */
    SoakingAlarm("02018001"),
    /**
     * 温度告警
     */
    TemperatureAlarm("02007001")
    ;
    private String value;
    AlarmType(String value) {
        this.value = value;
    }
    public String getValue() {
        return value;
    }
    public void setDesc(String value) {
        this.value = value;
    }
}

定义注解

采用注解方式 方便工厂注入

/**
 * @author Administrator
 * @auther KeShuai
 * @Date: 2020/08/20/10:14
 * @Description:
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AlarmAnnotation {
    /**
     * 相关类型名称
     */
    AlarmType value();
}

定义需要解析的数据对象

根据自己需要解析的数据 if判断完要设置的对象 自己定义

import lombok.Data;

/**
 * @author Administrator
 * @Auther: KeShuai
 * @Date: 2020/08/12/17:10
 * @Description:列表对象
 */
@Data
public class AttrListAlarmDto {

    private String id;

    private String value;

    private String doorId;

    private String devId;

    private String  alarmDesc;

    private String  batteryId;

    private String alarmFlag;

    private String alarmTime;

    private Integer statusFlag;

}

定义策略角色接口

/**
 * @author Administrator
 * @auther KeShuai
 * @Date: 2020/08/13/16:51
 * @Description: 信号量策略模式接口
 */
public interface AlarmRelated {
    /**
     * 判断接口
     * @param dto
     * @return
     */
    void batIf(AttrListAlarmDto dto);
}

定义工厂工具类和工厂

定义工厂的工具类

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author Administrator
 * @auther KeShuai
 * @Date: 2020/08/13/17:23
 * @Description: 工厂工具类
 */

@Component
public class SpringContextUtil implements ApplicationContextAware {

    private ApplicationContext context;

    public ApplicationContext getContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext context)throws BeansException {
        this.context = context;
    }
}

工厂对注解类进行判断生成策略接口对应的实现类


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * @author KeShuai
 * @auther KeShuai
 * @Date: 2020/08/13/17:24
 * @Description: 存取信号量对象的工厂
 */

@Component
public class AlarmRelatedFactory {
    @Autowired
    SpringContextUtil springContextUtil;

    private static Map<AlarmType, AlarmRelated> RelatedMap = Maps.newConcurrentMap();

    /**
     * 工厂将 Spring 装配的相关的 Bean 用 Map 保存起来
     */
    @PostConstruct
    public void init(){
        Map<String, Object> beanMap = springContextUtil.getContext().getBeansWithAnnotation(AlarmAnnotation.class);

        for(Object doorRelated : beanMap.values()) {
            AlarmAnnotation annotation = doorRelated.getClass().getAnnotation(AlarmAnnotation.class);
            RelatedMap.put(annotation.value(), (AlarmRelated)doorRelated);
        }
    }

    public static AlarmRelated createRelated(AlarmType relatedType) {
        return RelatedMap.get( relatedType );
    }
}

定义策略模式的实现类

此实现类就是相当于 if-else判断完 实现的需要的功能 if-else{ 每个实现类相当于括号这里面的功能}
以下列出一个例子 后续根据这个创建即可

/**
 * @author Administrator
 * @auther KeShuai
 * @Date: 2020/08/20/17:10
 * @Description: 机柜告警
 */
//本类的类名 这里不能重复不然工厂创建会查出俩条报错
@Component("AlarmTemperatureRelatedImpl")
//这里对应枚举类里面的判断数据
@AlarmAnnotation( value = AlarmType.TemperatureAlarm) 
public class AlarmTemperatureRelatedImpl implements AlarmRelated {
	//插入数据库的服务类引入
    @Autowired
    private AlarmService alarmService;
    @Override
    public void batIf(AttrListAlarmDto dto) {
        AlarmDTO batDto=new AlarmDTO();
        //判断枚举类里面值和传进来的值是否对应
        if (AlarmType.TemperatureAlarm.getDesc().equals(dto.getId())){
        	//存取操作
            batDto.setCabId(dto.getDevId());
            batDto.setAlarmDesc("温度过高告警");
            alarmService.save(batDto);

        }
    }
}

最后

最后的写在 服务上面的if 变成下图代码这样,如要加条件 则创建对应的策略实现类即可 在实现类里面写if判断完的服务就行了

//通过 枚举的值 反射获取枚举类 传入(枚举类,枚举值,枚举类的getVulue方法)
//data.getId() 传入对应刚才定义枚举类的值  如 ChangeAlarmJud("02008001")
//data.getId() = 02008001
AlarmType batName = EnumUtils.valueOf(AlarmType.class, data.getId(), AlarmType.class.getMethod("getValue"));
   if (batName != null) {
      //传入枚举对象获取
     AlarmRelated related = AlarmRelatedFactory.createRelated(batName);
                //如果等于空说明没有改判断对象
              if (related != null) {
                //传入对应的实现类判断
                related.batIf(data);
           }
}

写的代码比较粗糙 现在也是在学习进阶阶段 整合起来方便记录学习,还望各位大佬提出意见或者相互学习。谢谢!!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值