本文將以最簡單直接的方式,從零開始講解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中從設計到使用的完整生命周期。工廠模式的核心思想其實很簡單:定義一個創建對象的接口,但讓子類決定實例化哪個類。