Open Close Principle(OCP)
一.what is open-close-principle
OCP 是指软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
二.OCP的设计准则
- 对扩展开放:当需求变化时,我们应该能够通过添加新的代码来满足需求,而不是修改现有的代码。比如添加新的功能、支持新的类型等。
- 对修改关闭:一旦软件实体(模块、函数等)被实现,就不应该对其进行修改。这是为了确保软件的稳定性和可靠性。
- 使用抽象:通过抽象(如接口、抽象类等)来定义软件实体的行为,使得具体实现可以独立于抽象而变化。
三.举例
3.1 设备驱动反例
每次新增一种设备类型(例如SPI、USB),都要修改这个 switch,违反开闭原则。
点击查看代码
typedef enum {
DEV_UART,
DEV_GPIO,
DEV_I2C
} DevType;
int dev_open(DevType type, const char *name) {
switch (type) {
case DEV_UART:
// UART open logic
break;
case DEV_GPIO:
// GPIO open logic
break;
case DEV_I2C:
// I2C open logic
break;
default:
return -1;
}
// 同理 read/write/close 都要有switch
// 新增SPI或USB,就要改所有函数的switch
}
3.2 设备驱动正确实现
用结构体 + 函数指针表(vtable)模拟虚函数表,实现设备抽象。每个设备类型有一个“驱动”结构体,核心操作通过指针调用。
dev_abstraction.h
点击查看代码
// dev_abstraction.h
#ifndef DEV_ABSTRACTION_H
#define DEV_ABSTRACTION_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// 设备句柄(opaque,用户不关心内部)
typedef struct dev_handle dev_handle_t;
// 设备操作vtable(函数指针表)
typedef struct {
int (*open)(dev_handle_t *h, const char *name, int flags);
int (*read)(dev_handle_t *h, void *buf, size_t len);
int (*write)(dev_handle_t *h, const void *buf, size_t len);
void (*close)(dev_handle_t *h);
int (*ioctl)(dev_handle_t *h, int cmd, void *arg); // 可选控制
} dev_ops_t;
// 设备类型注册项
typedef struct dev_driver {
const char *type_name; // "uart", "gpio", "i2c", "spi"...
dev_ops_t ops;
size_t priv_size; // 私有数据大小(每个驱动自定义)
} dev_driver_t;
// 设备句柄结构(内部)
struct dev_handle {
const dev_driver_t *driver;
void *priv; // 驱动私有数据
// ... 可加引用计数等
};
// 核心API(永远不改)
void dev_register_driver(const dev_driver_t *driver);
// 创建设备句柄(按类型名查找驱动)
dev_handle_t *dev_create(const char *type_name);
// 通用操作(通过vtable调用)
int dev_open(dev_handle_t *h, const char *name, int flags);
int dev_read(dev_handle_t *h, void *buf, size_t len);
int dev_write(dev_handle_t *h, const void *buf, size_t len);
void dev_close(dev_handle_t *h);
int dev_ioctl(dev_handle_t *h, int cmd, void *arg);
#endif
dev_abstraction.c
点击查看代码
// dev_abstraction.c
#include "dev_abstraction.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_DRIVERS 32
static const dev_driver_t *drivers[MAX_DRIVERS] = {0};
static int driver_count = 0;
void dev_register_driver(const dev_driver_t *driver)
{
if (driver_count >= MAX_DRIVERS) {
fprintf(stderr, "too many device drivers\n");
return;
}
drivers[driver_count++] = driver;
}
static const dev_driver_t *find_driver(const char *type_name)
{
for (int i = 0; i < driver_count; i++) {
const dev_driver_t *d = drivers[i];
if (d && strcmp(d->type_name, type_name) == 0)
return d;
}
return NULL;
}
dev_handle_t *dev_create(const char *type_name)
{
const dev_driver_t *d = find_driver(type_name);
if (!d) {
fprintf(stderr, "unknown device type: %s\n", type_name);
return NULL;
}
dev_handle_t *h = malloc(sizeof(dev_handle_t));
if (!h) return NULL;
h->driver = d;
h->priv = (d->priv_size > 0) ? calloc(1, d->priv_size) : NULL;
return h;
}
// 通用操作(委托给vtable,永远不改)
int dev_open(dev_handle_t *h, const char *name, int flags)
{
if (!h || !h->driver || !h->driver->ops.open) return -1;
return h->driver->ops.open(h, name, flags);
}
int dev_read(dev_handle_t *h, void *buf, size_t len)
{
if (!h || !h->driver || !h->driver->ops.read) return -1;
return h->driver->ops.read(h, buf, len);
}
int dev_write(dev_handle_t *h, const void *buf, size_t len)
{
if (!h || !h->driver || !h->driver->ops.write) return -1;
return h->driver->ops.write(h, buf, len);
}
void dev_close(dev_handle_t *h)
{
if (!h || !h->driver || !h->driver->ops.close) return;
h->driver->ops.close(h);
free(h->priv);
free(h);
}
int dev_ioctl(dev_handle_t *h, int cmd, void *arg)
{
if (!h || !h->driver || !h->driver->ops.ioctl) return -1;
return h->driver->ops.ioctl(h, cmd, arg);
}
新增UART驱动,不需要修改核心代码。
uart_driver.c
点击查看代码
// uart_driver.c
#include "dev_abstraction.h"
#include <stdio.h> // 模拟实际硬件操作
typedef struct {
FILE *fp; // 模拟串口文件
} uart_priv_t;
static int uart_open(dev_handle_t *h, const char *name, int flags)
{
uart_priv_t *p = h->priv;
p->fp = fopen(name, "r+"); // 模拟 /dev/ttyS0
return p->fp ? 0 : -1;
}
static int uart_read(dev_handle_t *h, void *buf, size_t len)
{
uart_priv_t *p = h->priv;
return fread(buf, 1, len, p->fp);
}
static int uart_write(dev_handle_t *h, const void *buf, size_t len)
{
uart_priv_t *p = h->priv;
return fwrite(buf, 1, len, p->fp);
}
static void uart_close(dev_handle_t *h)
{
uart_priv_t *p = h->priv;
if (p->fp) fclose(p->fp);
}
static int uart_ioctl(dev_handle_t *h, int cmd, void *arg)
{
// 模拟设置波特率等
return 0;
}
static const dev_driver_t uart_driver = {
.type_name = "uart",
.ops = {
.open = uart_open,
.read = uart_read,
.write = uart_write,
.close = uart_close,
.ioctl = uart_ioctl
},
.priv_size = sizeof(uart_priv_t)
};
__attribute__((constructor))
static void register_uart(void)
{
dev_register_driver(&uart_driver);
}
main.c
点击查看代码
int main(void)
{
dev_handle_t *h = dev_create("uart");
if (!h) return 1;
if (dev_open(h, "/dev/ttyS0", 0) != 0) {
dev_close(h);
return 1;
}
char buf[128] = "Hello, device!";
dev_write(h, buf, strlen(buf));
memset(buf, 0, sizeof(buf));
dev_read(h, buf, sizeof(buf));
printf("Read: %s\n", buf);
dev_ioctl(h, 0x1234, NULL); // 自定义命令
dev_close(h);
// 新增"spi"驱动后,直接dev_create("spi")即可,无需改main
return 0;
}
浙公网安备 33010602011771号