当前位置: 首页 > news >正文

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 logicbreak;case DEV_GPIO:// GPIO open logicbreak;case DEV_I2C:// I2C open logicbreak;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 32static 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/ttyS0return 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")即可,无需改mainreturn 0;
}
http://www.jsqmd.com/news/403219/

相关文章:

  • 基于Opencv C# 开发的圆卡尺、矩形卡尺,直线卡尺、距离测量工具源码,代码运行正常,由实...
  • 智能客服智能体开发实战:基于扣子平台的新手指南
  • 基于神经网络的智能客服小程序设计与实现:从模型训练到生产部署全流程解析
  • Single Responsbility Principle(SRP)
  • Transformer 电商智能客服:从架构设计到性能优化的实战指南
  • 电商智能客服系统设计:从零搭建高可用对话引擎
  • 从零搭建智能客服工作流:基于Dify的实战入门指南
  • uniapp运行到鸿蒙手机模拟器因为文件夹中文名称报错
  • 具身智能:原理、算法与系统 第18章 模仿学习与人类示范
  • 扣子智能客服API新手入门指南:从接入到实战避坑
  • 企业智能客服平台大作业实战指南:从零搭建到性能优化
  • 基于模糊控制的改进动态窗口DWA算法功能介绍
  • 智能客服自动化问答系统实战:基于NLP与微服务架构的高效实现
  • 基于DeepSeek和RAG的智能客服系统:从零搭建到生产环境部署
  • 智能客服对接淘宝实战指南:从API集成到消息队列优化
  • 智能客服关键词匹配技术解析:从算法选型到生产环境优化
  • Python 办公自动化:批量处理 Excel/Word/PPT 实战教程
  • 影刀千牛智能客服系统架构解析与效率提升实战
  • 大规模语言模型在跨学科科学推理中的突破
  • 基于AI构建电话智能客服系统的架构设计与实战避坑指南
  • 智能客服系统产品经理实战指南:从需求分析到技术落地
  • 客服智能辅助系统实战:基于NLP的工单分类与自动回复架构设计
  • 提示工程架构师深度好文:Agentic AI如何实现跨平台与多设备协同
  • AI智能客服与知识库产品设计实战:从功能列表到原型实现
  • Chatbot为什么在各个领域需要:效率提升的技术实现与架构解析
  • 电商智能客服系统架构图:高并发场景下的效率优化实践
  • 智能客服系统MRCP入门指南:从协议解析到实战部署
  • 智能客服接入拼多多全流程实战:从API对接到生产环境部署
  • Python+微信API开发智能客服机器人:从接入到优化的全流程指南
  • 智能客服货盘系统实战:高并发场景下的架构设计与性能优化