文章目录
-
-
-
- 一、工厂模式的定义与核心价值
- [二、C 语言实现工厂模式的核心思路](#二、C 语言实现工厂模式的核心思路)
- [三、 5 个实例](#三、 5 个实例)
-
- [实例 1:简单工厂(形状创建)](#实例 1:简单工厂(形状创建))
- [实例 2:工厂方法(日志器创建)](#实例 2:工厂方法(日志器创建))
- [实例 3:简单工厂(硬件设备创建)](#实例 3:简单工厂(硬件设备创建))
- [实例 4:工厂方法(数据库连接创建)](#实例 4:工厂方法(数据库连接创建))
- [实例 5:内核风格工厂(内存块创建)](#实例 5:内核风格工厂(内存块创建))
- [四、Linux 内核中的工厂模式应用](#四、Linux 内核中的工厂模式应用)
- 五、实现注意事项
- 六、补充说明
-
-
一、工厂模式的定义与核心价值
工厂模式(Factory Pattern)是一种创建型设计模式,其核心是通过统一的 "工厂" 接口创建对象,而非直接调用malloc或构造函数。该模式将对象创建逻辑与使用逻辑解耦,隐藏对象创建的细节(如内存分配、初始化步骤),让客户端只需关注对象的使用,无需关心对象如何创建。
存在的意义:当对象创建过程复杂(需多步初始化、依赖外部配置或有多种变体),或需批量创建同类型对象时,直接在客户端创建对象会导致代码冗余、耦合紧密。工厂模式通过集中化的工厂统一管理对象创建,降低客户端与对象实现的耦合,同时便于后续扩展新的对象类型。
解决的问题:
- 客户端直接创建对象导致代码冗余,尤其是对象初始化步骤较多时;
- 对象类型频繁变化或新增时,需修改大量客户端代码,违反 "开闭原则";
- 对象创建细节(如内存分配、资源初始化)暴露给客户端,增加使用复杂度和出错风险。
二、C 语言实现工厂模式的核心思路
C 语言通过结构体封装对象与工厂 +函数指针定义创建接口实现模式,核心分为两类:
- 简单工厂(Simple Factory):一个工厂负责创建所有类型的对象,通过参数(如类型 ID)区分对象类型,适合对象类型较少且变化不频繁的场景;
- 工厂方法(Factory Method):为每种对象类型定义一个专属工厂(继承统一工厂接口),客户端通过对应的工厂创建对象,适合对象类型较多或频繁扩展的场景。

两种模式的核心都是 "工厂负责创建,客户端负责使用",区别在于工厂的粒度和扩展方式。
三、 5 个实例
实例 1:简单工厂(形状创建)
通过一个工厂根据类型参数(圆形 / 矩形)创建不同形状对象,适合对象类型较少的场景。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
// 1. 抽象产品:形状(统一接口)
typedef struct {
void (*draw)(const struct Shape* self); // 绘制方法
void (*destroy)(struct Shape* self); // 销毁方法
const char* type; // 形状类型
} Shape;
// 2. 具体产品1:圆形
typedef struct {
Shape base; // 继承抽象形状
float radius; // 圆形特有属性:半径
} Circle;
static void circle_draw(const Shape* self) {
const Circle* circle = (const Circle*)self;
printf("Drawing Circle: radius=%.1f\n", circle->radius);
}
static void circle_destroy(Shape* self) {
free(self);
}
// 具体产品2:矩形
typedef struct {
Shape base; // 继承抽象形状
float width; // 矩形特有属性:宽
float height; // 矩形特有属性:高
} Rectangle;
static void rect_draw(const Shape* self) {
const Rectangle* rect = (const Rectangle*)self;
printf("Drawing Rectangle: width=%.1f, height=%.1f\n", rect->width, rect->height);
}
static void rect_destroy(Shape* self) {
free(self);
}
// 3. 简单工厂:形状工厂(根据类型创建对象)
typedef enum { SHAPE_CIRCLE, SHAPE_RECTANGLE } ShapeType;
Shape* create_shape(ShapeType type, ...) {
// 使用可变参数处理不同形状的初始化参数
va_list args;
va_start(args, type);
Shape* shape = NULL;
switch (type) {
case SHAPE_CIRCLE: {
float radius = va_arg(args, double); // 可变参数读取半径(float提升为double)
Circle* circle = malloc(sizeof(Circle));
circle->base.type = "Circle";
circle->base.draw = circle_draw;
circle->base.destroy = circle_destroy;
circle->radius = radius;
shape = (Shape*)circle;
break;
}
case SHAPE_RECTANGLE: {
float width = va_arg(args, double);
float height = va_arg(args, double);
Rectangle* rect = malloc(sizeof(Rectangle));
rect->base.type = "Rectangle";
rect->base.draw = rect_draw;
rect->base.destroy = rect_destroy;
rect->width = width;
rect->height = height;
shape = (Shape*)rect;
break;
}
default:
printf("Unsupported shape type\n");
break;
}
va_end(args);
return shape;
}
// 客户端使用:通过工厂创建形状,无需关心具体实现
int main() {
// 1. 创建圆形(通过工厂+类型参数)
Shape* circle = create_shape(SHAPE_CIRCLE, 5.0f);
if (circle) {
printf("Created %s\n", circle->type);
circle->draw(circle);
circle->destroy(circle);
}
// 2. 创建矩形(通过工厂+类型参数)
Shape* rect = create_shape(SHAPE_RECTANGLE, 4.0f, 6.0f);
if (rect) {
printf("\nCreated %s\n", rect->type);
rect->draw(rect);
rect->destroy(rect);
}
return 0;
}
以上代码运行结果为
Created Circle
Drawing Circle: radius=5.0
Created Rectangle
Drawing Rectangle: width=4.0, height=6.0
其对应 的UML图例如下

即:简单工厂create_shape通过ShapeType参数区分对象类型,客户端只需传入类型和初始化参数,即可获取完整对象。新增形状(如三角形)只需修改工厂的switch分支,无需修改客户端代码。
实例 2:工厂方法(日志器创建)
为每种日志器(控制台日志 / 文件日志)定义专属工厂,客户端通过对应工厂创建对象,适合频繁扩展对象类型的场景。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// 1. 抽象产品:日志器(统一接口)
typedef struct {
void (*log)(const struct Logger* self, const char* level, const char* msg);
void (*destroy)(struct Logger* self);
const char* type;
} Logger;
// 2. 抽象工厂:日志器工厂(统一创建接口)
typedef struct {
Logger* (*create_logger)(struct LoggerFactory* self);
void (*destroy_factory)(struct LoggerFactory* self);
} LoggerFactory;
// 3. 具体产品1:控制台日志器
typedef struct {
Logger base;
} ConsoleLogger;
static void console_log(const Logger* self, const char* level, const char* msg) {
(void)self;
char time_buf[20];
time_t t = time(NULL);
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", localtime(&t));
printf("[%s] [%s] %s\n", time_buf, level, msg);
}
static void console_destroy(Logger* self) {
free(self);
}
// 具体工厂1:控制台日志器工厂
typedef struct {
LoggerFactory base;
} ConsoleLoggerFactory;
static Logger* console_create_logger(LoggerFactory* self) {
(void)self;
ConsoleLogger* logger = malloc(sizeof(ConsoleLogger));
logger->base.type = "ConsoleLogger";
logger->base.log = console_log;
logger->base.destroy = console_destroy;
return (Logger*)logger;
}
static void console_destroy_factory(LoggerFactory* self) {
free(self);
}
// 初始化控制台日志工厂
LoggerFactory* create_console_log_factory() {
ConsoleLoggerFactory* factory = malloc(sizeof(ConsoleLoggerFactory));
factory->base.create_logger = console_create_logger;
factory->base.destroy_factory = console_destroy_factory;
return (LoggerFactory*)factory;
}
// 具体产品2:文件日志器
typedef struct {
Logger base;
const char* filename; // 文件日志特有属性:日志文件名
} FileLogger;
static void file_log(const Logger* self, const char* level, const char* msg) {
const FileLogger* file_logger = (const FileLogger*)self;
FILE* f = fopen(file_logger->filename, "a");
if (!f) return;
char time_buf[20];
time_t t = time(NULL);
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", localtime(&t));
fprintf(f, "[%s] [%s] %s\n", time_buf, level, msg);
fclose(f);
printf("Logged to %s: [%s] %s\n", file_logger->filename, level, msg);
}
static void file_destroy(Logger* self) {
free(self);
}
// 具体工厂2:文件日志器工厂(需传入文件名参数)
typedef struct {
LoggerFactory base;
const char* filename; // 工厂持有文件日志的配置参数
} FileLoggerFactory;
static Logger* file_create_logger(LoggerFactory* self) {
FileLoggerFactory* file_factory = (FileLoggerFactory*)self;
FileLogger* logger = malloc(sizeof(FileLogger));
logger->base.type = "FileLogger";
logger->base.log = file_log;
logger->base.destroy = file_destroy;
logger->filename = file_factory->filename; // 传递配置参数到产品
return (Logger*)logger;
}
static void file_destroy_factory(LoggerFactory* self) {
free(self);
}
// 初始化文件日志工厂(传入文件名)
LoggerFactory* create_file_log_factory(const char* filename) {
FileLoggerFactory* factory = malloc(sizeof(FileLoggerFactory));
factory->filename = filename;
factory->base.create_logger = file_create_logger;
factory->base.destroy_factory = file_destroy_factory;
return (LoggerFactory*)factory;
}
// 客户端使用:通过专属工厂创建日志器,扩展新日志器无需修改旧代码
int main() {
// 1. 使用控制台日志工厂
LoggerFactory* console_factory = create_console_log_factory();
Logger* console_logger = console_factory->create_logger(console_factory);
printf("=== Using %s ===\n", console_logger->type);
console_logger->log(console_logger, "INFO", "Program started");
console_logger->destroy(console_logger);
console_factory->destroy_factory(console_factory);
// 2. 使用文件日志工厂
LoggerFactory* file_factory = create_file_log_factory("app.log");
Logger* file_logger = file_factory->create_logger(file_factory);
printf("\n=== Using %s ===\n", file_logger->type);
file_logger->log(file_logger, "ERROR", "Config load failed");
file_logger->destroy(file_logger);
file_factory->destroy_factory(file_factory);
return 0;
}
以上代码运行结果为
=== Using ConsoleLogger ===
[2025-10-26 16:16:29] [INFO] Program started
=== Using FileLogger ===
Logged to app.log: [ERROR] Config load failed
其对应 的UML图例如下

即:工厂方法模式为每种日志器定义专属工厂,新增日志器(如网络日志)只需添加 "网络日志产品 + 网络日志工厂",无需修改现有工厂和客户端代码,完全符合 "开闭原则"。
实例 3:简单工厂(硬件设备创建)
模拟嵌入式系统中通过工厂创建不同硬件设备(UART/SPI),工厂负责设备的初始化配置,客户端直接使用设备功能。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
// 1. 抽象产品:硬件设备(统一接口)
typedef struct {
bool (*init)(struct Device* self, uint32_t base_addr); // 设备初始化
void (*send)(struct Device* self, const uint8_t* data, size_t len); // 发送数据
void (*destroy)(struct Device* self);
const char* type;
uint32_t base_addr; // 设备基地址(通用属性)
} Device;
// 2. 具体产品1:UART设备
typedef struct {
Device base;
uint32_t baud_rate; // UART特有属性:波特率
} UARTDevice;
static bool uart_init(Device* self, uint32_t base_addr) {
UARTDevice* uart = (UARTDevice*)self;
uart->base.base_addr = base_addr;
uart->baud_rate = 115200; // 默认波特率
printf("UART initialized at 0x%08X, baud rate: %d\n", base_addr, uart->baud_rate);
return true;
}
static void uart_send(Device* self, const uint8_t* data, size_t len) {
UARTDevice* uart = (UARTDevice*)self;
printf("UART sending %zu bytes: ", len);
for (size_t i = 0; i < len; i++) {
printf("%02X ", data[i]);
}
printf("\n");
}
static void uart_destroy(Device* self) {
free(self);
}
// 具体产品2:SPI设备
typedef struct {
Device base;
uint32_t clk_freq; // SPI特有属性:时钟频率
} SPIDevice;
static bool spi_init(Device* self, uint32_t base_addr) {
SPIDevice* spi = (SPIDevice*)self;
spi->base.base_addr = base_addr;
spi->clk_freq = 1000000; // 默认1MHz
printf("SPI initialized at 0x%08X, clock freq: %d Hz\n", base_addr, spi->clk_freq);
return true;
}
static void spi_send(Device* self, const uint8_t* data, size_t len) {
SPIDevice* spi = (SPIDevice*)self;
printf("SPI sending %zu bytes: ", len);
for (size_t i = 0; i < len; i++) {
printf("%02X ", data[i]);
}
printf("\n");
}
static void spi_destroy(Device* self) {
free(self);
}
// 3. 简单工厂:设备工厂(根据类型创建硬件设备)
typedef enum { DEVICE_UART, DEVICE_SPI } DeviceType;
Device* create_device(DeviceType type) {
Device* device = NULL;
switch (type) {
case DEVICE_UART: {
UARTDevice* uart = malloc(sizeof(UARTDevice));
uart->base.type = "UART";
uart->base.init = uart_init;
uart->base.send = uart_send;
uart->base.destroy = uart_destroy;
device = (Device*)uart;
break;
}
case DEVICE_SPI: {
SPIDevice* spi = malloc(sizeof(SPIDevice));
spi->base.type = "SPI";
spi->base.init = spi_init;
spi->base.send = spi_send;
spi->base.destroy = spi_destroy;
device = (Device*)spi;
break;
}
default:
printf("Unsupported device type\n");
break;
}
return device;
}
// 客户端使用:通过工厂创建设备,统一调用初始化和发送接口
int main() {
uint8_t data[] = {0xAA, 0xBB, 0xCC};
size_t data_len = sizeof(data)/sizeof(data[0]);
// 1. 创建并使用UART设备
Device* uart = create_device(DEVICE_UART);
if (uart) {
printf("=== Using %s Device ===\n", uart->type);
uart->init(uart, 0x10000000); // 初始化UART(基地址0x10000000)
uart->send(uart, data, data_len);
uart->destroy(uart);
}
// 2. 创建并使用SPI设备
Device* spi = create_device(DEVICE_SPI);
if (spi) {
printf("\n=== Using %s Device ===\n", spi->type);
spi->init(spi, 0x10001000); // 初始化SPI(基地址0x10001000)
spi->send(spi, data, data_len);
spi->destroy(spi);
}
return 0;
}
以上代码运行结果为
=== Using UART Device ===
UART initialized at 0x10000000, baud rate: 115200
UART sending 3 bytes: AA BB CC
=== Using SPI Device ===
SPI initialized at 0x10001000, clock freq: 1000000 Hz
SPI sending 3 bytes: AA BB CC
其对应 的UML图例如下

即:工厂create_device负责创建硬件设备并绑定初始化、发送等方法,客户端只需调用统一接口即可操作不同设备,无需关心 UART 和 SPI 的底层差异,符合嵌入式开发中 "硬件抽象" 的设计思想。
实例 4:工厂方法(数据库连接创建)
为每种数据库(MySQL/SQLite)定义专属工厂,工厂负责创建连接并处理连接配置,客户端直接使用连接执行 SQL。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// 1. 抽象产品:数据库连接(统一接口)
typedef struct {
bool (*connect)(struct DBConnection* self, const char* config); // 连接数据库
bool (*execute)(struct DBConnection* self, const char* sql); // 执行SQL
void (*disconnect)(struct DBConnection* self); // 断开连接
void (*destroy)(struct DBConnection* self);
const char* type;
} DBConnection;
// 2. 抽象工厂:数据库连接工厂(统一创建接口)
typedef struct {
DBConnection* (*create_connection)(struct DBFactory* self);
void (*destroy_factory)(struct DBFactory* self);
} DBFactory;
// 3. 具体产品1:MySQL连接
typedef struct {
DBConnection base;
char config[128]; // 存储连接配置(如"host:port/db")
} MySQLConnection;
static bool mysql_connect(DBConnection* self, const char* config) {
MySQLConnection* mysql_conn = (MySQLConnection*)self;
strncpy(mysql_conn->config, config, sizeof(mysql_conn->config)-1);
printf("MySQL connecting to: %s\n", config);
printf("MySQL connected successfully\n");
return true;
}
static bool mysql_execute(DBConnection* self, const char* sql) {
(void)self;
printf("MySQL executing SQL: %s\n", sql);
return true; // 模拟执行成功
}
static void mysql_disconnect(DBConnection* self) {
MySQLConnection* mysql_conn = (MySQLConnection*)self;
printf("MySQL disconnecting from: %s\n", mysql_conn->config);
}
static void mysql_destroy(DBConnection* self) {
free(self);
}
// 具体工厂1:MySQL连接工厂
typedef struct {
DBFactory base;
} MySQLFactory;
static DBConnection* mysql_create_conn(DBFactory* self) {
(void)self;
MySQLConnection* mysql_conn = malloc(sizeof(MySQLConnection));
mysql_conn->base.type = "MySQL";
mysql_conn->base.connect = mysql_connect;
mysql_conn->base.execute = mysql_execute;
mysql_conn->base.disconnect = mysql_disconnect;
mysql_conn->base.destroy = mysql_destroy;
return (DBConnection*)mysql_conn;
}
static void mysql_destroy_factory(DBFactory* self) {
free(self);
}
DBFactory* create_mysql_factory() {
MySQLFactory* factory = malloc(sizeof(MySQLFactory));
factory->base.create_connection = mysql_create_conn;
factory->base.destroy_factory = mysql_destroy_factory;
return (DBFactory*)factory;
}
// 具体产品2:SQLite连接
typedef struct {
DBConnection base;
char db_file[64]; // SQLite特有:数据库文件路径
} SQLiteConnection;
static bool sqlite_connect(DBConnection* self, const char* config) {
SQLiteConnection* sqlite_conn = (SQLiteConnection*)self;
strncpy(sqlite_conn->db_file, config, sizeof(sqlite_conn->db_file)-1);
printf("SQLite opening file: %s\n", config);
printf("SQLite connected successfully\n");
return true;
}
static bool sqlite_execute(DBConnection* self, const char* sql) {
(void)self;
printf("SQLite executing SQL: %s\n", sql);
return true; // 模拟执行成功
}
static void sqlite_disconnect(DBConnection* self) {
SQLiteConnection* sqlite_conn = (SQLiteConnection*)self;
printf("SQLite closing file: %s\n", sqlite_conn->db_file);
}
static void sqlite_destroy(DBConnection* self) {
free(self);
}
// 具体工厂2:SQLite连接工厂
typedef struct {
DBFactory base;
} SQLiteFactory;
static DBConnection* sqlite_create_conn(DBFactory* self) {
(void)self;
SQLiteConnection* sqlite_conn = malloc(sizeof(SQLiteConnection));
sqlite_conn->base.type = "SQLite";
sqlite_conn->base.connect = sqlite_connect;
sqlite_conn->base.execute = sqlite_execute;
sqlite_conn->base.disconnect = sqlite_disconnect;
sqlite_conn->base.destroy = sqlite_destroy;
return (DBConnection*)sqlite_conn;
}
static void sqlite_destroy_factory(DBFactory* self) {
free(self);
}
DBFactory* create_sqlite_factory() {
SQLiteFactory* factory = malloc(sizeof(SQLiteFactory));
factory->base.create_connection = sqlite_create_conn;
factory->base.destroy_factory = sqlite_destroy_factory;
return (DBFactory*)factory;
}
// 客户端使用:通过专属工厂创建数据库连接,统一调用SQL接口
int main() {
// 1. 使用MySQL工厂创建连接
DBFactory* mysql_factory = create_mysql_factory();
DBConnection* mysql_conn = mysql_factory->create_connection(mysql_factory);
if (mysql_conn) {
printf("=== Using %s Connection ===\n", mysql_conn->type);
mysql_conn->connect(mysql_conn, "localhost:3306/mydb");
mysql_conn->execute(mysql_conn, "SELECT * FROM users");
mysql_conn->disconnect(mysql_conn);
mysql_conn->destroy(mysql_conn);
}
mysql_factory->destroy_factory(mysql_factory);
// 2. 使用SQLite工厂创建连接
DBFactory* sqlite_factory = create_sqlite_factory();
DBConnection* sqlite_conn = sqlite_factory->create_connection(sqlite_factory);
if (sqlite_conn) {
printf("\n=== Using %s Connection ===\n", sqlite_conn->type);
sqlite_conn->connect(sqlite_conn, "./data.db");
sqlite_conn->execute(sqlite_conn, "SELECT * FROM logs");
sqlite_conn->disconnect(sqlite_conn);
sqlite_conn->destroy(sqlite_conn);
}
sqlite_factory->destroy_factory(sqlite_factory);
return 0;
}
以上代码运行结果为
=== Using MySQL Connection ===
MySQL connecting to: localhost:3306/mydb
MySQL connected successfully
MySQL executing SQL: SELECT * FROM users
MySQL disconnecting from: localhost:3306/mydb
=== Using SQLite Connection ===
SQLite opening file: ./data.db
SQLite connected successfully
SQLite executing SQL: SELECT * FROM logs
SQLite closing file: ./data.db
其对应 的UML图例如下

即:工厂方法模式让每种数据库连接有专属工厂,客户端切换数据库时只需替换工厂实例,无需修改连接和 SQL 执行逻辑,适合多数据库兼容的项目(如跨平台应用)。
实例 5:内核风格工厂(内存块创建)
模拟 Linux 内核中通过工厂创建预初始化的内存块,工厂负责内存分配和初始化,客户端直接使用内存块存储数据,符合内核对性能和内存效率的要求。
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// 1. 抽象产品:内核内存块(统一接口)
#define BLOCK_DATA_SIZE 256 // 内存块数据区大小
typedef struct {
void (*write)(struct KernelMemBlock* self, const void* data, size_t len); // 写入数据
void (*read)(struct KernelMemBlock* self, void* buf, size_t len); // 读取数据
void (*destroy)(struct KernelMemBlock* self);
const char* type;
uint8_t data[BLOCK_DATA_SIZE]; // 数据存储区
size_t used; // 已使用字节数
} KernelMemBlock;
// 2. 定义C语言静态函数(替代C++ Lambda,供所有内存块共用)
// 通用写入实现(普通内存/DMA内存共用)
static void kernel_mem_block_write(KernelMemBlock* self, const void* data, size_t len) {
if (!self || !data) return; // 空指针保护
if (self->used + len > BLOCK_DATA_SIZE) {
printf("MemBlock full: used=%zu, need=%zu\n", self->used, len);
return;
}
memcpy(self->data + self->used, data, len);
self->used += len;
printf("%s wrote %zu bytes\n", self->type, len);
}
// 通用读取实现(普通内存/DMA内存共用)
static void kernel_mem_block_read(KernelMemBlock* self, void* buf, size_t len) {
if (!self || !buf) return; // 空指针保护
size_t read_len = (len > self->used) ? self->used : len;
memcpy(buf, self->data, read_len);
printf("%s read %zu bytes\n", self->type, read_len);
}
// 通用销毁实现
static void kernel_mem_block_destroy(KernelMemBlock* self) {
free(self);
}
// 3. 简单工厂:内核内存块工厂(创建预初始化的内存块)
typedef enum { MEM_BLOCK_NORMAL, MEM_BLOCK_DMA } MemBlockType; // 普通内存/DMA内存
KernelMemBlock* create_kernel_mem_block(MemBlockType type) {
KernelMemBlock* block = malloc(sizeof(KernelMemBlock));
if (!block) return NULL;
// 初始化通用属性
memset(block->data, 0, BLOCK_DATA_SIZE);
block->used = 0;
// 绑定通用函数(替代Lambda,C语言支持静态函数指针赋值)
block->write = kernel_mem_block_write;
block->read = kernel_mem_block_read;
block->destroy = kernel_mem_block_destroy;
switch (type) {
case MEM_BLOCK_NORMAL:
block->type = "NormalMemBlock";
// 普通内存块:无额外初始化(通用函数已绑定)
break;
case MEM_BLOCK_DMA:
block->type = "DMAMemBlock";
// DMA内存块:模拟DMA专用内存初始化(如内存对齐,此处简化)
printf("DMAMemBlock: Simulated memory alignment (4KB)\n");
break;
default:
free(block);
printf("Unsupported memory block type\n");
return NULL;
}
printf("Created %s (size: %d bytes)\n", block->type, BLOCK_DATA_SIZE);
return block;
}
// 客户端使用:模拟内核模块使用内存块
int main() {
const char* test_data = "Kernel memory block test";
size_t data_len = strlen(test_data);
char read_buf[BLOCK_DATA_SIZE];
// 1. 创建并使用普通内存块
KernelMemBlock* normal_block = create_kernel_mem_block(MEM_BLOCK_NORMAL);
if (normal_block) {
printf("\n=== Using %s ===\n", normal_block->type);
normal_block->write(normal_block, test_data, data_len);
memset(read_buf, 0, sizeof(read_buf));
normal_block->read(normal_block, read_buf, data_len);
printf("Read data: %s\n", read_buf);
normal_block->destroy(normal_block);
}
// 2. 创建并使用DMA内存块
KernelMemBlock* dma_block = create_kernel_mem_block(MEM_BLOCK_DMA);
if (dma_block) {
printf("\n=== Using %s ===\n", dma_block->type);
dma_block->write(dma_block, test_data, data_len);
memset(read_buf, 0, sizeof(read_buf));
dma_block->read(dma_block, read_buf, data_len);
printf("Read data: %s\n", read_buf);
dma_block->destroy(dma_block);
}
return 0;
}
以上代码运行结果为
Created NormalMemBlock (size: 256 bytes)
=== Using NormalMemBlock ===
NormalMemBlock wrote 24 bytes
NormalMemBlock read 24 bytes
Read data: Kernel memory block test
DMAMemBlock: Simulated memory alignment (4KB)
Created DMAMemBlock (size: 256 bytes)
=== Using DMAMemBlock ===
DMAMemBlock wrote 24 bytes
DMAMemBlock read 24 bytes
Read data: Kernel memory block test
其对应 的UML图例如下

即:模拟 Linux 内核中 "内存块工厂" 的设计,工厂创建内存块时预初始化数据区和读写方法,客户端直接调用统一接口操作内存,无需关心内存是否为 DMA 专用或普通内存,符合内核对 "抽象与封装" 的要求。
四、Linux 内核中的工厂模式应用
- 文件系统 inode 工厂(
inode_alloc与iget) :内核中inode(索引节点)是文件系统的核心对象,inode_alloc函数作为 "简单工厂",负责分配inode结构体并初始化通用属性(如引用计数、类型);不同文件系统(如 ext4、btrfs)通过iget(inode get)函数作为 "工厂方法",从磁盘读取 inode 数据并初始化文件系统特有属性(如 ext4 的i_block_group),最终返回完整的inode对象。 - 网络套接字工厂(
socket系统调用) :socket系统调用是典型的 "简单工厂",通过domain(协议域,如 AF_INET)、type(套接字类型,如 SOCK_STREAM)参数,创建不同类型的套接字对象(如 TCP 套接字、UDP 套接字)。内核通过__sock_create函数统一管理套接字的创建,具体协议(TCP/UDP)的初始化由对应的proto_ops接口完成。 - 设备驱动工厂(
platform_driver_register) :平台设备驱动中,platform_driver_register函数作为 "工厂方法",为每种平台设备(如 GPIO 控制器、UART 控制器)注册专属驱动。当内核检测到匹配的设备时,通过驱动的probe函数(工厂的创建逻辑)初始化设备并创建驱动对象,实现 "设备与驱动的动态匹配"。 - 内存分配工厂(
kmalloc与vmalloc) :kmalloc和vmalloc是内核中的 "内存块工厂":kmalloc创建物理连续的内存块,vmalloc创建虚拟连续但物理不连续的内存块。两者作为 "工厂方法",隐藏内存分配的底层细节(如伙伴系统、页表映射),客户端只需传入内存大小即可获取内存块,无需关心内存的物理分布。 - 信号量工厂(
sema_init与down/up) :内核信号量(struct semaphore)的创建通过sem_init函数完成,该函数作为 "简单工厂",初始化信号量的计数和等待队列。客户端通过down(获取信号量)和up(释放信号量)接口使用信号量,无需关心等待队列的管理和调度细节,工厂已封装所有创建和初始化逻辑。
五、实现注意事项
- 对象接口的一致性 :抽象产品(如
Shape、Logger)的函数指针接口需统一,确保不同具体产品的方法参数和返回值一致,客户端才能通过抽象接口透明使用不同对象。 - 资源释放的完整性 :工厂创建的对象必须提供明确的
destroy方法,确保内存分配的对象能被正确释放;工厂本身(尤其是工厂方法模式中的工厂)也需提供destroy_factory方法,避免工厂实例的内存泄漏。 - 简单工厂与工厂方法的选择 :
- 简单工厂:适合对象类型少(如≤5 种)、变化不频繁的场景,代码简洁但扩展时需修改工厂;
- 工厂方法:适合对象类型多、频繁扩展的场景,扩展时无需修改旧代码但工厂数量较多,需权衡代码复杂度。
- 线程安全的保障 :多线程环境下,若工厂共享全局状态(如对象计数器、资源池),需通过互斥锁(如
pthread_mutex_t)保护,避免并发创建对象导致的状态不一致或内存错误。 - 参数传递的安全性 :简单工厂通过参数区分对象类型时,需校验参数合法性(如
switch的default分支);工厂方法模式中,工厂的配置参数(如文件日志的文件名)需确保非空且合法,避免空指针或非法配置导致的崩溃。
六、补充说明
- 工厂模式与抽象工厂模式的区别:工厂模式专注于创建单一类型的对象 (如日志器、形状),抽象工厂模式专注于创建多个相关的对象家族(如 "日志格式化器 + 日志输出器");前者是 "单一对象创建",后者是 "家族对象创建"。
- 工厂模式的扩展:
- 对象池化 :工厂可预分配一批对象存入 "对象池",客户端请求时直接从池获取,避免频繁
malloc/free的开销(如内核的 slab 分配器); - 懒加载创建:工厂在客户端首次请求对象时才创建,而非启动时创建所有对象,减少初始化资源消耗(如内核模块的驱动工厂)。
- 对象池化 :工厂可预分配一批对象存入 "对象池",客户端请求时直接从池获取,避免频繁
- 适用场景:对象创建复杂、需批量创建同类型对象、对象类型需扩展、需隐藏创建细节(如内核、嵌入式开发)等场景。
通过工厂模式,C 语言程序(尤其是 Linux 内核)能够集中管理对象创建,降低耦合、提升扩展性,是构建模块化、可维护系统的核心技术之一。内核中大量核心组件(如 inode、套接字、内存块)均采用工厂模式设计,体现了 "创建与使用分离" 的设计思想。
|---------------------|
| 点击下面关注,获取最新最全分享,不迷路 |