本文将以最简单直接的方式,从零开始讲解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:设计期
- 分析需要创建哪些类型的对象
- 提取公共接口形成抽象产品类
- 为每个具体类型实现产品接口
阶段2:编译期
- 工厂类根据编译选项(如USE_ASPEED_GPIO)
- 确定包含哪些具体实现
- 生成平台特定的工厂实现
阶段3:运行时
- 客户端调用工厂创建方法
- 工厂实例化具体产品对象
- 返回产品基类指针/引用
- 客户端通过基类接口使用产品
阶段4:销毁期
- 产品超出作用域自动销毁(智能指针)
- 或显式调用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. 工厂模式的关键优势
- 创建与使用分离:客户端不需要知道具体实现类
- 易于扩展:添加新类型只需新增产品类并修改工厂
- 统一管理:集中控制对象创建过程
- 平台无关:通过工厂隔离平台特定代码
6. 何时使用工厂模式
在OpenBMC中遇到以下情况时考虑使用工厂模式:
- 需要创建不同平台(Aspeed/Nuvoton)的硬件操作类
- 系统需要支持多种实现方式(如sysfs/直接寄存器访问)
- 对象创建过程复杂或需要统一管理
- 希望隔离具体实现类与客户端代码
通过这个简明的流程说明,应该能够清晰理解工厂模式在OpenBMC中从设计到使用的完整生命周期。工厂模式的核心思想其实很简单:定义一个创建对象的接口,但让子类决定实例化哪个类。