本文将以最简单直接的方式,从零开始讲解OpenBMC中工厂模式的完整工作流程,包括从设计到使用的全生命周期。

1. 工厂模式最简示例

我们先从一个最基础的工厂模式实现开始:

// 产品接口
class GpioPin {
public:virtual void setValue(bool value) = 0;virtual ~GpioPin() = default;
};// 具体产品A
class AspeedGpio : public GpioPin {
public:void setValue(bool value) override {std::cout << "Aspeed GPIO set to " << value << std::endl;}
};// 具体产品B
class SysfsGpio : public GpioPin {
public:void setValue(bool value) override {std::cout << "Sysfs GPIO set to " << value << std::endl;}
};// 简单工厂
class GpioFactory {
public:static std::unique_ptr<GpioPin> create(const std::string& type) {if (type == "aspeed") {return std::make_unique<AspeedGpio>();} else {return std::make_unique<SysfsGpio>();}}
};

2. 完整工作流程(从创建到使用)

步骤1:定义产品接口

首先确定需要创建的对象类型和公共接口

// 定义所有GPIO操作必须实现的接口
class GpioPin {
public:virtual void setDirection(Direction dir) = 0;virtual bool getValue() = 0;virtual void setValue(bool value) = 0;virtual ~GpioPin() = default;
};

步骤2:实现具体产品

为每个平台或类型创建具体实现

// Aspeed平台专用实现
class AspeedGpio : public GpioPin {void setValue(bool value) override {// 直接操作Aspeed芯片寄存器reg_write(ASPEED_GPIO_REG, value);}// 其他接口实现...
};// 通用sysfs实现
class SysfsGpio : public GpioPin {void setValue(bool value) override {// 通过Linux sysfs接口操作std::ofstream file("/sys/class/gpio/gpioX/value");file << (value ? "1" : "0");}// 其他接口实现...
};

步骤3:创建工厂类

实现决定创建哪种产品的逻辑

class GpioFactory {
public:static std::unique_ptr<GpioPin> create() {// 通过编译选项或运行时检测决定使用哪种实现#ifdef USE_ASPEED_GPIOreturn std::make_unique<AspeedGpio>();#elsereturn std::make_unique<SysfsGpio>();#endif}
};

步骤4:客户端使用

其他代码通过工厂获取产品实例

// 在需要GPIO的地方
void controlLed() {// 通过工厂创建GPIO实例auto ledPin = GpioFactory::create();// 使用统一接口操作,不关心具体实现ledPin->setValue(true);std::this_thread::sleep_for(1s);ledPin->setValue(false);
}

3. 工厂模式的生命周期

阶段1:设计期

  1. 分析需要创建哪些类型的对象
  2. 提取公共接口形成抽象产品类
  3. 为每个具体类型实现产品接口

阶段2:编译期

  1. 工厂类根据编译选项(如USE_ASPEED_GPIO)
  2. 确定包含哪些具体实现
  3. 生成平台特定的工厂实现

阶段3:运行时

  1. 客户端调用工厂创建方法
  2. 工厂实例化具体产品对象
  3. 返回产品基类指针/引用
  4. 客户端通过基类接口使用产品

阶段4:销毁期

  1. 产品超出作用域自动销毁(智能指针)
  2. 或显式调用delete释放资源

4. OpenBMC真实案例流程

以创建传感器为例的完整工作流:

// 1. 定义传感器接口
class Sensor {
public:virtual double readValue() = 0;virtual ~Sensor() = default;
};// 2. 实现具体传感器
class TemperatureSensor : public Sensor {double readValue() override {// 实际读取硬件温度值return read_hw_register(0x2A);}
};class FanSpeedSensor : public Sensor {double readValue() override {// 读取风扇转速return read_fan_rpm();}
};// 3. 创建传感器工厂
class SensorFactory {
public:static std::unique_ptr<Sensor> create(const std::string& type) {if (type == "temp") {return std::make_unique<TemperatureSensor>();} else if (type == "fan") {return std::make_unique<FanSpeedSensor>();}return nullptr;}
};// 4. 系统初始化时注册传感器
void initSensors() {auto& sensorManager = SensorManager::getInstance();sensorManager.addSensor("cpu_temp", SensorFactory::create("temp"));sensorManager.addSensor("fan1", SensorFactory::create("fan"));
}// 5. 其他模块使用传感器
void checkTemperature() {auto tempSensor = SensorManager::getInstance().getSensor("cpu_temp");if (tempSensor->readValue() > 80.0) {triggerCooling();}
}

5. 工厂模式的关键优势

  1. 创建与使用分离:客户端不需要知道具体实现类
  2. 易于扩展:添加新类型只需新增产品类并修改工厂
  3. 统一管理:集中控制对象创建过程
  4. 平台无关:通过工厂隔离平台特定代码

6. 何时使用工厂模式

在OpenBMC中遇到以下情况时考虑使用工厂模式:

  1. 需要创建不同平台(Aspeed/Nuvoton)的硬件操作类
  2. 系统需要支持多种实现方式(如sysfs/直接寄存器访问)
  3. 对象创建过程复杂或需要统一管理
  4. 希望隔离具体实现类与客户端代码

通过这个简明的流程说明,应该能够清晰理解工厂模式在OpenBMC中从设计到使用的完整生命周期。工厂模式的核心思想其实很简单:定义一个创建对象的接口,但让子类决定实例化哪个类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95254.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95254.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95254.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决:Error updating changes: detected dubious ownership in repository at

在通过 Git Bash 提交项目代码时输入 git add . 命令后&#xff0c;报错&#xff1a;Error updating changes: detected dubious ownership in repository at ...这是因为 该项目的所有者 与 现在的用户 不一致 比如说&#xff1a; 该项目的所有者是 Administrator&#xff0c;…

DataEase V2 社区版安装部署

参考&#xff1a;使用外置 MySQL 部署 DataEase v2 - FIT2CLOUD 知识库 一、下载安装包 开源社区 - FIT2CLOUD 飞致云 选择社区版下载 下载后上传到 linux 的目录 &#xff08;要求至少200G&#xff09; 二、在MySQL8中创建数据库 # 创建DataEase库 CREATE DATABASE datae…

nginx高性能web服务器

web服务基础介绍 一、Web服务核心流程 #mermaid-svg-NCj4hbRIvvgMXmcK {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-NCj4hbRIvvgMXmcK .error-icon{fill:#552222;}#mermaid-svg-NCj4hbRIvvgMXmcK .error-text{fil…

_init__.py的作用

目录 场景1:没有 `__init__.py` 的情况 场景2:有 `__init__.py` 并导入模块 场景3:用 `__all__` 定义"推荐工具" 注意:工具箱内部的工具互相调用 情况1:在 `__init__.py` 中导入模块 情况2:在 `__init__.py` 中直接导入模块里的功能 关键原则 在 Python 中,__…

浏览器面试题及详细答案 88道(12-22)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

开发避坑指南(23):Tomcat高版本URL特殊字符限制问题解决方案(RFC 7230 RFC 3986)

异常信息 java.lang.IllegalArgumentException: 在请求目标中找到无效字符[/order/show?orderType01&orderTitle0xe50x8f0xa30xe50xb20xb80xe50x8a0xa80xe60x800x81&pageNum1 ]。有效字符在RFC 7230和RFC 3986中定义org.apache.coyote.http11.Http11InputBuffer.parse…

HTTPS的应用层协议

HTTPS的应用层协议 方案 5 - 非对称加密 对称加密 证书认证 在客户端和服务器刚一建⽴连接的时候, 服务器给客户端返回一个 证书&#xff0c;证书包含了之前服务端的公钥, 也包含了网站的身份信息. 客户端进行认证 当客户端获取到这个证书之后, 会对证书进行校验(防止证书是伪…

【SpringBoot】05 容器功能 - SpringBoot底层注解的应用与实战 - @Configuration + @Bean

文章目录前言一、创建两个组件二、使用传统方式源代码解释三、使用SpringBoot方法源代码解释四、查看是否添加到组件中查看自定义组件名配置类在容器中注册的是单实例组件配置类本身也是容器中的一个组件Configuration的proxyBeanMethods属性&#xff1a;代理bean的方法proxyBe…

c#联合Halcon进行OCR字符识别(含halcon-25.05 百度网盘)

1.下载安装halcon 通过网盘分享的文件&#xff1a;halcon-25.05.0.0-x64-win64 链接: https://pan.baidu.com/s/1XAx-8ZQM-ZHkgHIc-dhCYw 提取码: whek 2.c#环境配置 创建test_halcon_ocr项目 找到halcon的安装路径 我的&#xff1a; D:\halcon\HALCON-25.05-Progress\bin\x64…

丝杆支撑座怎样助力升降设备实现智能化?

丝杆支撑座作为传动系统中的关键支撑部件&#xff0c;凭借其高刚性、抗冲击及精准定位能力&#xff0c;广泛应用于重型机械与升降设备领域&#xff0c;为设备提供稳定可靠的轴向承载与径向支撑&#xff0c;确保高负荷工况下的安全运行。电梯 / 升降平台&#xff1a;液压电梯的辅…

Notta:高效智能的音频转文字工具

本文转载自&#xff1a;Notta&#xff1a;高效智能的音频转文字工具 - Hello123 ** 一、产品简介 Notta 是一款基于 AI 语音识别引擎的语音转文字工具&#xff0c;支持 58 种语言的转录和 42 种语言的翻译。用户可通过实时录音或上传音频 / 视频文件&#xff08;如 MP3、WAV …

Docker私有仓库创建及Docky存储与网络配置(小白的“升级打怪”成长之路)

目录 一、Docker私有仓库创建 1、在一台安装Docker私有仓库的主机上添加docker-compose 命令 2、安装docker-ce服务 3、Docker 镜像加速 4、安装Harbor仓库 5、使用脚本安装仓库 6、网站登陆 7、客户端使用Harbor仓库 二、Docky存储与网络配置 1、存储与网络 挂载主机…

谷歌ADK接入文件操作MCP

文章目录MCP基础概念文件操作服务器文件操作MCP接入谷歌ADK项目创建多轮对话代码MCP基础概念 MCP技术体系中&#xff0c;会将外部工具运行脚本称作服务器&#xff0c;而接入这些外部工具的大模型运行环境称作客户端。 一个客户端可以接入多个不同类型的服务器&#xff0c;但都…

高光谱技术的独特优势

高光谱技术凭借其‌纳米级连续光谱采集能力‌和‌图谱合一的探测模式‌&#xff0c;在多个领域展现出不可替代的独特优势&#xff1a;一、光谱维度&#xff1a;精细物质指纹识别‌纳米级连续光谱解析‌ 通过 ‌5-10nm带宽的数百个连续波段‌&#xff08;最高330个通道&#xff…

基于Vue+Element UI集成高德地图的完整实践指南

本次开发使用deepseek 简直如虎添翼得心应手 生成模拟数据、解决报错那真是嘎嘎地 在 Vue Element UI 项目中引入高德地图 具体实现步骤&#xff1a; 高德开放平台&#xff1a;注册账号 → 进入控制台 → 创建应用 → 获取 Web端(JS API)的Key https://lbs.amap.com/ 这里需要…

Day50--图论--98. 所有可达路径(卡码网),797. 所有可能的路径

Day50–图论–98. 所有可达路径&#xff08;卡码网&#xff09;&#xff0c;797. 所有可能的路径 刷今天的内容之前&#xff0c;要先去《代码随想录》网站&#xff0c;先看完&#xff1a;图论理论基础和深度优先搜索理论基础。做完之后可以看题解。有余力&#xff0c;把广度优先…

Python 异常捕获

一、获取未知错误try:# 相关处理逻辑 异常后面输出print(输入信息……) except Exception as e:print(未知错误,e)二、获取已知错误except 错误单词&#xff08;来源于错误信息的第一个单词&#xff09;多个已知错误使用 except XXXXX:try:# 相关处理逻辑 异常后面输出print…

RIOT、RT-Thread 和 FreeRTOS 是三种主流的实时操作系统

RIOT、RT-Thread 和 FreeRTOS 是三种主流的实时操作系统&#xff08;RTOS&#xff09;&#xff0c;专为嵌入式系统和物联网&#xff08;IoT&#xff09;设备设计。它们在架构、功能、生态和应用场景上有显著差异&#xff0c;以下是详细对比&#xff1a;1. 架构与设计理念特性RI…

【FAQ】Win11创建资源不足绕开微软账号登录

Win11安装资源限制 因为 Windows 11 有两项强制检测 VMware 8 默认没提供&#xff1a; TPM 2.0&#xff08;可信平台模块&#xff09;Secure Boot&#xff08;安全启动&#xff09; 一步到位解决办法&#xff08;官方兼容方式&#xff09; 关闭虚拟机电源编辑虚拟机设置 选项 →…

Docker使用----(安装_Windows版)

一、Docker Docker 镜像就像是一个软件包&#xff0c;里面包括了应用程序的代码、运行所需的库和工具、配置文件等等&#xff0c;所有这些都打包在一起&#xff0c;以确保应用程序在不同的计算机上运行时&#xff0c;都能保持一致性。 可以把 Docker 镜像想象成一个软件安装文件…