C语言模板方法模式详解与实践
1. 什么是模板方法模式?
模板方法模式定义了一个算法的骨架,将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
2. 为什么需要模板方法模式?
- 封装固定的算法流程
- 提供算法框架
- 允许子类定制具体实现
- 代码复用
- 控制子类扩展
3. 实际应用场景
- 数据处理流程
- 文件解析流程
- 设备初始化流程
- 数据库操作流程
- 通信协议处理
4. 代码实现
4.1 UML 关系图
4.2 头文件 (data_processor.h)
#ifndef DATA_PROCESSOR_H
#define DATA_PROCESSOR_H
#include <stdbool.h>
// 数据处理器结构体
typedef struct {
void* data;
int data_size;
// 具体步骤的函数指针
bool (*validate)(void* data, int size);
void* (*transform)(void* data, int size, int* new_size);
bool (*save)(void* data, int size);
// 清理函数
void (*cleanup)(void* data);
} DataProcessor;
// 模板方法:处理数据
bool process_data(DataProcessor* processor);
// 创建具体处理器
DataProcessor* create_file_processor(void);
DataProcessor* create_network_processor(void);
// 销毁处理器
void destroy_processor(DataProcessor* processor);
#endif // DATA_PROCESSOR_H
4.3 实现文件 (data_processor.c)
#include "data_processor.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 模板方法实现
bool process_data(DataProcessor* processor) {
printf("开始处理数据...\n");
// 步骤1:验证
if (!processor->validate(processor->data, processor->data_size)) {
printf("数据验证失败\n");
return false;
}
printf("数据验证通过\n");
// 步骤2:转换
int new_size;
void* transformed_data = processor->transform(processor->data,
processor->data_size,
&new_size);
if (!transformed_data) {
printf("数据转换失败\n");
return false;
}
printf("数据转换完成\n");
// 步骤3:保存
bool save_result = processor->save(transformed_data, new_size);
// 清理转换后的数据
if (processor->cleanup) {
processor->cleanup(transformed_data);
}
if (!save_result) {
printf("数据保存失败\n");
return false;
}
printf("数据保存成功\n");
return true;
}
// 文件处理器具体实现
static bool file_validate(void* data, int size) {
const char* file_data = (const char*)data;
return (file_data && size > 0);
}
static void* file_transform(void* data, int size, int* new_size) {
// 模拟文件数据转换
char* transformed = (char*)malloc(size + 1);
memcpy(transformed, data, size);
transformed[size] = '\0';
*new_size = size + 1;
return transformed;
}
static bool file_save(void* data, int size) {
// 模拟文件保存
printf("保存文件数据,大小:%d\n", size);
return true;
}
// 网络处理器具体实现
static bool network_validate(void* data, int size) {
const char* net_data = (const char*)data;
return (net_data && size >= 4); // 假设最小包长度为4
}
static void* network_transform(void* data, int size, int* new_size) {
// 模拟网络数据转换
char* transformed = (char*)malloc(size * 2);
memcpy(transformed, data, size);
memcpy(transformed + size, data, size);
*new_size = size * 2;
return transformed;
}
static bool network_save(void* data, int size) {
// 模拟网络数据保存
printf("保存网络数据,大小:%d\n", size);
return true;
}
// 创建文件处理器
DataProcessor* create_file_processor(void) {
DataProcessor* processor = (DataProcessor*)malloc(sizeof(DataProcessor));
processor->validate = file_validate;
processor->transform = file_transform;
processor->save = file_save;
processor->cleanup = free;
return processor;
}
// 创建网络处理器
DataProcessor* create_network_processor(void) {
DataProcessor* processor = (DataProcessor*)malloc(sizeof(DataProcessor));
processor->validate = network_validate;
processor->transform = network_transform;
processor->save = network_save;
processor->cleanup = free;
return processor;
}
// 销毁处理器
void destroy_processor(DataProcessor* processor) {
if (processor->cleanup && processor->data) {
processor->cleanup(processor->data);
}
free(processor);
}
4.4 使用示例 (main.c)
#include "data_processor.h"
#include <stdio.h>
#include <string.h>
int main() {
// 测试文件处理器
printf("=== 文件处理器测试 ===\n");
DataProcessor* file_processor = create_file_processor();
char file_data[] = "Hello, File!";
file_processor->data = file_data;
file_processor->data_size = strlen(file_data);
bool file_result = process_data(file_processor);
printf("文件处理结果:%s\n\n", file_result ? "成功" : "失败");
// 测试网络处理器
printf("=== 网络处理器测试 ===\n");
DataProcessor* network_processor = create_network_processor();
char network_data[] = "Network Data";
network_processor->data = network_data;
network_processor->data_size = strlen(network_data);
bool network_result = process_data(network_processor);
printf("网络处理结果:%s\n", network_result ? "成功" : "失败");
// 清理资源
destroy_processor(file_processor);
destroy_processor(network_processor);
return 0;
}
5. 代码分析
5.1 关键设计点
- 模板方法固定算法框架
- 函数指针实现多态
- 统一的处理接口
- 资源管理完整
5.2 实现特点
- 算法步骤清晰
- 扩展性好
- 代码复用
- 错误处理完善
6. 编译和运行
gcc -c data_processor.c -o data_processor.o
gcc -c main.c -o main.o
gcc data_processor.o main.o -o template_demo
7. 注意事项
- 内存管理安全
- 函数指针初始化
- 错误处理完整性
- 资源释放及时
8. 改进建议
- 添加更多钩子方法
- 实现并行处理
- 添加处理状态记录
- 支持处理链
9. 总结
模板方法模式通过定义算法骨架,让具体实现延迟到子类中完成,实现了代码复用和扩展性。这种模式特别适合处理具有固定流程但细节可变的场景。
参考资料
- 《设计模式:可复用面向对象软件的基础》
- 《C语言程序设计》
- 《算法设计与分析》