前提概要
** 本文介绍工厂加策略模式的设计模式 因为对设备操作解析报文的全量数据太多需要判断 所以以下对数据解析的 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);
}
}
写的代码比较粗糙 现在也是在学习进阶阶段 整合起来方便记录学习,还望各位大佬提出意见或者相互学习。谢谢!!