先降低圈复杂度
1 个赞
考虑解耦,业务判断预警和预警报警模块拆分,这里只判断是否预警,由预警报警模块单独判断是否重复预警,是否需要入库。这样后续万一要改报警判断逻辑或者发信息通知之类的会清晰一点。
能跑就是好代码
献丑了,我觉得 @unique u佬的解题挺好的。我来水一个另一种思路。
1.利用map做简易策略模式封装,在bifunction里面处理对应的分支逻辑
2.利用数据库查询,减少对应代码判断过程
3.查询的数据必须做非空判断,以防npe
4.对于entry对象的封装和保存,建议封装成方法,提高可读性
对于这种多重判断的,我的经验是,如果你能把这些数据维度拉平,那最好做个策略模式,简单明了。如果不能,那么可能需要考虑分级,分组处理。
private Map<String, BiFunction<DevicePollAlarmConfig, deviceData>> map = new HashMap() {{
put("wd", (devicePollAlarmConfig, deviceData) -> {
// do your work...
/*
1.alarmInfoMapper.selectAlarm(2, deviceData.getMn(), "wd");// 这里查询可以带上时间,可以减少代码里面的判断。其次查询出来的报警信息可能为空,需要做非空判断
2.AlarmInfo实体类的处理,可以封装成方法,减少单个方法的行数,可读性更强
*/
});
}};
public void newTest() {
for (DevicePollAlarmConfig devicePollAlarmConfig : devicePollAlarmConfigs) {
map.get(devicePollAlarmConfig.getPollCode());
}
}
2 个赞
List<CompletableFuture<Void>> futures = devicePollAlarmConfigs.stream()
.map(devicePollAlarmConfig ->
CompletableFuture.runAsync(() -> {
// 你的业务代码
}, 你的线程池(必须设置不能用默认的))
)
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
看變量命名應該0和2 是警報類型吧或者狀態吧
1.这么多if判断怎么去优化更优雅呢
也沒有太好的方法,抽離 if 中的執行邏輯為一個個函数、使用衛語句、提前跳出、合併判定條件、策略模式等等,但是需要衡量代碼可讀性,如果if 雖然多但是代碼可讀性好,我認為是沒必須要去優化的 寫好注釋和例子說明 這些if為啥要這些判定 才是重要的
2. 接收数据 处理数据 需要去多线程处理吗
首先有必要使用多線程嗎?接收和處理數據是否有前後關係?目前的處理對響應時間有影響?
@Component
public class DevicePollAlarmTask {
private CompositePollCodeStrategy compositePollCodeStrategy;
@Autowired
public void setCompositePollCodeStrategy(CompositePollCodeStrategy compositePollCodeStrategy) {
this.compositePollCodeStrategy = compositePollCodeStrategy;
}
private AlarmInfoMapper alarmInfoMapper;
@Autowired
public void setAlarmInfoMapper(AlarmInfoMapper alarmInfoMapper) {
this.alarmInfoMapper = alarmInfoMapper;
}
public void execute(DeviceData deviceData) {
List<DevicePollAlarmConfig> devicePollAlarmConfigs = alarmInfoMapper.selectAlarmConfigList();
for (DevicePollAlarmConfig devicePollAlarmConfig : devicePollAlarmConfigs) {
compositePollCodeStrategy.run(devicePollAlarmConfig, deviceData);
List<AlarmInfo> notDealList = alarmInfoMapper.selectAlarmList(0);
if (!notDealList.isEmpty()) {
WebSocketServer.sendToOne("123", JsonUtil.toJson(notDealList));
}
}
}
}
/**
* PollCodeStrategy 是一个抽象类,定义了处理特定轮询代码策略的基础框架。
* 它要求所有的具体策略实现两个核心方法:获取轮询代码的方法和执行策略的方法。
* 这个类设计用于设备轮询报警的情景,其中每种轮询代码对应一种特定的处理策略。
* <b>注意:</b>实现前请参考{@link WDPollCodeStrategy}
*/
public abstract class PollCodeStrategy {
/**
* 获取当前策略的轮询代码。
* 轮询代码是一个字符串标识符,用于区分不同的轮询策略。
*
* @return 轮询代码的字符串表示。
*/
public abstract String getCode();
/**
* 执行策略的具体操作。
* 此方法根据提供的设备轮询报警配置和设备数据执行策略逻辑。
* 它由具体的策略实现类根据实际业务逻辑进行实现。
*
* @param devicePollAlarmConfig 设备轮询报警配置,包含轮询代码和相关阈值等配置信息。
* @param deviceData 设备数据,包含当前轮询周期内从设备采集到的数据。
*/
public abstract void run(DevicePollAlarmConfig devicePollAlarmConfig, DeviceData deviceData);
}
@Component
public class CompositePollCodeStrategy extends PollCodeStrategy {
private Map<String, PollCodeStrategy> pollCodeStrategyMap;
@Autowired
public void setPollCodeStrategyMap(Map<String, PollCodeStrategy> pollCodeStrategyMap) {
this.pollCodeStrategyMap = pollCodeStrategyMap;
}
@Override
public void run(DevicePollAlarmConfig devicePollAlarmConfig, DeviceData deviceData) {
String pollCode = devicePollAlarmConfig.getPollCode();
PollCodeStrategy strategy = pollCodeStrategyMap.get(pollCode);
if (strategy != null) {
strategy.run(devicePollAlarmConfig, deviceData);
} else {
// 处理未找到匹配策略的情况
}
}
@Override
public String getCode() {
// 由于这是组合策略,不需要实现此方法,默认返回Null
return null;
}
}
@Component("wd")
class WDPollCodeStrategy extends PollCodeStrategy {
private final static String CODE = "wd";
private AlarmInfoMapper alarmInfoMapper;
@Autowired
public void setAlarmInfoMapper(AlarmInfoMapper alarmInfoMapper) {
this.alarmInfoMapper = alarmInfoMapper;
}
@Override
public void run(DevicePollAlarmConfig devicePollAlarmConfig, DeviceData deviceData) {
String tempFlag = deviceData.getTempFlag();
String mn = deviceData.getMn();
double lowerLimit = devicePollAlarmConfig.getLowerLimit();
double upperLimit = devicePollAlarmConfig.getUpperLimit();
double currentTemp = Double.parseDouble(deviceData.getTemp());
// 从目前代码来看 似乎后续用不到 那返回一个数字 是否可以
AlarmInfo checkAlarmInfo;
if (
Objects.equals("N", tempFlag)
&& (currentTemp > upperLimit || currentTemp < lowerLimit)
&& (checkAlarmInfo = alarmInfoMapper.selectAlarm(0, mn, code)) == null
) {
AlarmInfo dealAlarm = alarmInfoMapper.selectAlarm(2, mn, code);
// 存在已处理的同类型报警 且处理时间在5分钟内 不再报警
if (dealAlarm != null) {
if (LocalDateTime.now().minusMinutes(5).isBefore(dealAlarm.getUpdateTime())) {
return;
}
dealAlarm.setIsDeal(1);
alarmInfoMapper.updateById(dealAlarm);
}
// 可以抽离到一个函数
AlarmInfo alarmInfo = new AlarmInfo();
alarmInfo.setMn(mn);
alarmInfo.setDeviceName("恒温系统");
alarmInfo.setAlarmContent("温度超限" + currentTemp + "℃" + "(阈值" + lowerLimit + "℃~" + upperLimit + "℃)");
alarmInfo.setAlarmType(2);
alarmInfo.setAlarmCode(code);
alarmInfoMapper.insert(alarmInfo);
}
}
@Override
public String getCode() {
return CODE;
}
}
@Component("sd")
class SDPollCodeStrategy extends PollCodeStrategy {
private final static String CODE= "sd";
private AlarmInfoMapper alarmInfoMapper;
@Autowired
public void setAlarmInfoMapper(AlarmInfoMapper alarmInfoMapper) {
this.alarmInfoMapper = alarmInfoMapper;
}
@Override
public void run(DevicePollAlarmConfig devicePollAlarmConfig, DeviceData deviceData) {
if (Objects.equals("N", deviceData.getHumidityFlag())) {
// do something
}
}
@Override
public String getCode() {
return CODE;
}
}
报警吧