C语言-策略模式详解与实践

C语言-策略模式详解与实践 - 多协议解析器实现

1. 什么是策略模式?

策略模式定义了一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式让算法独立于使用它的客户端而变化。

2. 为什么需要策略模式?

  • 支持多种协议解析
  • 动态切换解析策略
  • 易于扩展新协议
  • 解耦协议解析与业务逻辑
  • 简化协议处理流程

3. 实际应用场景

  • 串口多协议解析
  • 网络协议处理
  • 数据格式转换
  • 通信协议适配
  • 设备驱动开发

4. 代码实现

4.1 UML 关系图

ProtocolParser
+parse()
+validate()
ModbusParser
+parse()
+validate()
CustomParser
+parse()
+validate()

4.2 头文件 (protocol_parser.h)

#ifndef PROTOCOL_PARSER_H
#define PROTOCOL_PARSER_H

#include <stdint.h>
#include <stdbool.h>

// 协议类型
typedef enum {
    PROTOCOL_MODBUS = 0,
    PROTOCOL_CUSTOM,
    PROTOCOL_DEBUG,
    PROTOCOL_MAX
} ProtocolType;

// 解析结果
typedef struct {
    uint8_t cmd;        // 命令码
    uint8_t* data;      // 数据
    uint16_t length;    // 数据长度
    bool success;       // 是否成功
    char error[64];     // 错误信息
} ParseResult;

// 解析器接口
typedef bool (*ValidateFunc)(const uint8_t* data, uint16_t length);
typedef bool (*ParseFunc)(const uint8_t* data, uint16_t length, ParseResult* result);

// 协议解析器
typedef struct {
    ValidateFunc validate;   // 数据校验
    ParseFunc parse;         // 数据解析
    const char* name;        // 协议名称
} ProtocolParser;

// 创建解析器
ProtocolParser* create_parser(ProtocolType type);

// 销毁解析器
void destroy_parser(ProtocolParser* parser);

// 解析数据
bool parse_protocol_data(ProtocolParser* parser, 
                        const uint8_t* data, 
                        uint16_t length, 
                        ParseResult* result);

#endif // PROTOCOL_PARSER_H

4.3 实现文件 (protocol_parser.c)

#include "protocol_parser.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Modbus协议解析
static bool modbus_validate(const uint8_t* data, uint16_t length) {
    if (length < 4) return false;
    
    // 简单的CRC校验
    uint8_t sum = 0;
    for (uint16_t i = 0; i < length - 1; i++) {
        sum += data[i];
    }
    return (sum == data[length - 1]);
}

static bool modbus_parse(const uint8_t* data, uint16_t length, ParseResult* result) {
    if (!modbus_validate(data, length)) {
        strcpy(result->error, "Modbus校验失败");
        result->success = false;
        return false;
    }
    
    result->cmd = data[1];
    result->data = (uint8_t*)malloc(length - 3);
    memcpy(result->data, &data[2], length - 3);
    result->length = length - 3;
    result->success = true;
    return true;
}

// 自定义协议解析
static bool custom_validate(const uint8_t* data, uint16_t length) {
    if (length < 5) return false;
    return (data[0] == 0xAA && data[length-1] == 0x55);
}

static bool custom_parse(const uint8_t* data, uint16_t length, ParseResult* result) {
    if (!custom_validate(data, length)) {
        strcpy(result->error, "自定义协议校验失败");
        result->success = false;
        return false;
    }
    
    result->cmd = data[1];
    result->data = (uint8_t*)malloc(length - 4);
    memcpy(result->data, &data[2], length - 4);
    result->length = length - 4;
    result->success = true;
    return true;
}

// 调试协议解析
static bool debug_validate(const uint8_t* data, uint16_t length) {
    return (length > 0 && data[0] == 0xDD);
}

static bool debug_parse(const uint8_t* data, uint16_t length, ParseResult* result) {
    if (!debug_validate(data, length)) {
        strcpy(result->error, "调试协议校验失败");
        result->success = false;
        return false;
    }
    
    result->cmd = 0xFF;
    result->data = (uint8_t*)malloc(length - 1);
    memcpy(result->data, &data[1], length - 1);
    result->length = length - 1;
    result->success = true;
    return true;
}

// 协议解析器表
static const ProtocolParser parsers[] = {
    {modbus_validate, modbus_parse, "Modbus"},
    {custom_validate, custom_parse, "Custom"},
    {debug_validate, debug_parse, "Debug"}
};

ProtocolParser* create_parser(ProtocolType type) {
    if (type >= PROTOCOL_MAX) return NULL;
    
    ProtocolParser* parser = (ProtocolParser*)malloc(sizeof(ProtocolParser));
    memcpy(parser, &parsers[type], sizeof(ProtocolParser));
    return parser;
}

void destroy_parser(ProtocolParser* parser) {
    free(parser);
}

bool parse_protocol_data(ProtocolParser* parser, 
                        const uint8_t* data, 
                        uint16_t length, 
                        ParseResult* result) {
    printf("使用%s协议解析数据\n", parser->name);
    return parser->parse(data, length, result);
}

4.4 使用示例 (main.c)

#include "protocol_parser.h"
#include <stdio.h>

void print_result(const ParseResult* result) {
    if (result->success) {
        printf("解析成功:\n");
        printf("命令码: 0x%02X\n", result->cmd);
        printf("数据长度: %d\n", result->length);
        printf("数据内容: ");
        for (int i = 0; i < result->length; i++) {
            printf("%02X ", result->data[i]);
        }
        printf("\n");
    } else {
        printf("解析失败: %s\n", result->error);
    }
}

void cleanup_result(ParseResult* result) {
    if (result->data) {
        free(result->data);
        result->data = NULL;
    }
}

int main() {
    // Modbus协议测试
    printf("=== Modbus协议测试 ===\n");
    uint8_t modbus_data[] = {0x01, 0x03, 0x11, 0x22, 0x37};
    ProtocolParser* modbus_parser = create_parser(PROTOCOL_MODBUS);
    ParseResult modbus_result = {0};
    parse_protocol_data(modbus_parser, modbus_data, sizeof(modbus_data), &modbus_result);
    print_result(&modbus_result);
    cleanup_result(&modbus_result);
    
    // 自定义协议测试
    printf("\n=== 自定义协议测试 ===\n");
    uint8_t custom_data[] = {0xAA, 0x01, 0x33, 0x44, 0x55};
    ProtocolParser* custom_parser = create_parser(PROTOCOL_CUSTOM);
    ParseResult custom_result = {0};
    parse_protocol_data(custom_parser, custom_data, sizeof(custom_data), &custom_result);
    print_result(&custom_result);
    cleanup_result(&custom_result);
    
    // 调试协议测试
    printf("\n=== 调试协议测试 ===\n");
    uint8_t debug_data[] = {0xDD, 0x55, 0x66, 0x77};
    ProtocolParser* debug_parser = create_parser(PROTOCOL_DEBUG);
    ParseResult debug_result = {0};
    parse_protocol_data(debug_parser, debug_data, sizeof(debug_data), &debug_result);
    print_result(&debug_result);
    cleanup_result(&debug_result);
    
    // 清理资源
    destroy_parser(modbus_parser);
    destroy_parser(custom_parser);
    destroy_parser(debug_parser);
    
    return 0;
}

5. 代码分析

5.1 关键设计点

  1. 统一的解析器接口
  2. 策略的动态选择
  3. 完整的错误处理
  4. 资源管理安全

5.2 实现特点

  1. 函数指针实现多态
  2. 协议解析解耦
  3. 内存管理完善
  4. 扩展性良好

6. 编译和运行

gcc -c protocol_parser.c -o protocol_parser.o
gcc -c main.c -o main.o
gcc protocol_parser.o main.o -o protocol_demo

7. 注意事项

  1. 协议数据校验
  2. 内存管理安全
  3. 错误处理完整
  4. 协议兼容性

8. 改进建议

  1. 添加协议版本支持
  2. 实现协议转换功能
  3. 添加协议缓存机制
  4. 支持协议分片处理

9. 总结

策略模式通过封装不同的协议解析算法,实现了协议解析的灵活切换和扩展。这种模式特别适合处理多协议解析的场景。

参考资料

  1. 《设计模式:可复用面向对象软件的基础》
  2. 《C语言程序设计》
  3. 《通信协议设计》
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值