Fork me on GitHub

设备数据解析设计模式

最佳实践:采用 策略模式(Strategy Pattern) + 工厂模式(Factory Pattern) 组合,实现高扩展、高可维护的多设备数据解析。

1. 策略模式

封装不同设备的解析算法

// 策略接口:所有设备类型的数据解析器都必须实现
public interface DeviceDataParseStrategy {

    /**
     * 解析设备上报的原始字节数据
     * @param rawData  设备上报的原始字节数组
     * @param deviceId 设备ID(卡号)
     * @return 统一的数据对象
     */
    DeviceDataDTO parse(byte[] rawData, String deviceId);
}

// 示例:设备类型A的解析策略
@Component("typeADataParseStrategy")
public class TypeADataParseStrategy implements DeviceDataParseStrategy {

    @Override
    public DeviceDataDTO parse(byte[] rawData, String deviceId) {
        DeviceDataDTO dto = new DeviceDataDTO();
        dto.setDeviceId(deviceId);
        dto.setReceiveTime(DateUtil.now()); // Hutool 获取当前时间

        // 类型A专属解析逻辑(示例)
        // 假设协议:偏移0-1字节为亮度,2-3字节为电压(0.1V单位)
        int brightness = ByteUtil.bytesToShort(rawData, 0);         // Hutool 字节工具
        double voltage = ByteUtil.bytesToShort(rawData, 2) / 10.0;

        dto.getExtData().put("brightness", brightness);
        dto.getExtData().put("voltage", voltage);
        // 可继续解析电流、故障码等...

        return dto;
    }
}

// 示例:设备类型B的解析策略(协议完全不同)
@Component("typeBDataParseStrategy")
public class TypeBDataParseStrategy implements DeviceDataParseStrategy {

    @Override
    public DeviceDataDTO parse(byte[] rawData, String deviceId) {
        DeviceDataDTO dto = new DeviceDataDTO();
        dto.setDeviceId(deviceId);
        dto.setReceiveTime(DateUtil.now());

        // 类型B专属解析逻辑(示例)
        // 假设使用IEEE754浮点数表示开关状态和温度
        int status = rawData[0] & 0xFF;
        float temperature = ByteUtil.bytesToFloat(rawData, 1);

        dto.getExtData().put("switchStatus", status == 1 ? "ON" : "OFF");
        dto.getExtData().put("temperature", temperature);

        return dto;
    }
}

2. 工厂模式

根据设备类型动态获取解析策略

@Service
public class DeviceDataParseFactory {

 // Spring 自动注入所有解析策略实现,key 为 Bean 名称
 private final Map<String, DeviceDataParseStrategy> strategyMap;

 public DeviceDataParseFactory(Map<String, DeviceDataParseStrategy> strategyMap) {
     this.strategyMap = strategyMap;
 }

 public DeviceDataParseStrategy getStrategy(String deviceType) {
     // 使用 Hutool 优化命名规则
     String beanName = StrUtil.lowerFirst(deviceType) + "DataParseStrategy";

     DeviceDataParseStrategy strategy = strategyMap.get(beanName);
     if (strategy == null) {
         throw new UnsupportedOperationException("不支持的设备类型解析: " + deviceType);
     }
     return strategy;
 }
}
  1. 在 Service 层统一调用(推荐方式)
@Service
public class DeviceDataService {

    @Autowired
    private DeviceDataParseFactory parseFactory;

    /**
     * 处理设备上报数据
     * @param deviceType 设备类型
     * @param rawData    原始字节数据
     * @param deviceId   设备ID
       */
        public void handleUploadData(String deviceType, byte[] rawData, String deviceId) {
        // 1. 使用工厂 + 策略动态解析
        // 通过工厂根据设备类型获取对应的解析策略对象
        // 体现了工厂模式:运行时自动选择正确实现
        // 体现了策略模式:不同设备使用完全独立的解析算法
        DeviceDataParseStrategy strategy = parseFactory.getStrategy(deviceType);

        // 调用策略的 parse 方法执行专属解析逻辑
        // 返回统一DTO,便于后续统一存储、展示、告警等业务处理
        DeviceDataDTO dto = strategy.parse(rawData, deviceId);

        // 2. 统一业务处理(存储、告警、统计等)
        // saveToDatabase(dto);
        // checkAlarm(dto);
        log.info("设备数据解析成功 deviceId={} type={} data={}", deviceId, deviceType, dto.getExtData());
        }
    }
posted @ 2025-12-30 21:26  秋夜雨巷  阅读(60)  评论(0)    收藏  举报