第3章 抽象工厂模式实现平台适配层:产品族约束、配置驱动、扩展点与风险

3.1 边界与分层

抽象工厂模式在 Framework 层中主要承担平台适配层的职责,其边界位于 Framework 核心逻辑与底层操作系统/硬件平台之间。该层负责将一组相关的平台抽象对象(产品族)统一创建,从而隔离上层代码对具体平台依赖。

层级角色边界描述
Framework 核心调用者只依赖抽象产品接口,不感知具体平台实现
平台适配层抽象工厂 + 具体工厂封装平台差异,按配置创建产品族
底层系统/硬件资源提供方提供系统调用、驱动接口、HAL 能力

3.2 组件职责

  • 抽象工厂(AdaptorFactory):声明创建一组抽象产品的方法,例如 createThread()、createMutex()、createFileSystem()。
  • 具体工厂(LinuxAdaptorFactory / ZephyrAdaptorFactory):实现每个抽象方法,返回对应平台的实际产品实例。
  • 抽象产品(Thread / Mutex / FileSystem):定义平台无关的接口规范。
  • 具体产品(LinuxThread / ZephyrMutex):封装平台特定的系统调用或 HAL 函数。
  • 配置解析器:读取运行时配置或编译时宏,决定使用哪个具体工厂。

3.3 产品族约束

产品族约束是抽象工厂模式的核心前提——某一平台下,所有具体产品必须彼此兼容。例如 Linux 平台下线程、互斥量、文件系统实现应使用同一套系统调用集(pthread + glibc),不能混入 Zephyr 的 POSIX 子集实现。

// 平台适配层抽象工厂接口
class PlatformAdaptor {
public:
    virtual ~PlatformAdaptor() = default;
    virtual Thread* createThread(const char* name) = 0;
    virtual Mutex* createMutex() = 0;
    virtual FileSystem* createFileSystem() = 0;
};

// Linux 具体工厂:保证所有产品使用同一套系统调用族
class LinuxAdaptor : public PlatformAdaptor {
public:
    Thread* createThread(const char* name) override { return new LinuxThread(name); }
    Mutex* createMutex() override { return new PthreadMutex(); }
    FileSystem* createFileSystem() override { return new LinuxFileSystem(); }
};

违反产品族约束会直接导致运行时二进制不兼容或链接错误。Framework 层设计时应将产品族约束作为编译期静态检查项。

3.4 配置驱动

具体工厂的选择策略分为编译时与运行时两种:

  • 编译时配置:通过 CMake 变量或宏定义指定平台,例如 -DTARGET_PLATFORM=ZEPHYR,在 #if 中条件编译具体工厂。
  • 运行时配置:通过 JSON/YAML 配置文件或环境变量动态加载工厂,适用于 FPGA/模拟器切换场景。
// 运行时配置示例(JSON)
{
  "platform": "zephyr",
  "thread_stack_size": 4096,
  "use_static_mutex": false
}

3.5 数据流/控制流/信任链路

数据流:上层代码 → 抽象工厂 factory.createThread() → 具体工厂 LinuxAdaptor::createThread() → 具体产品 LinuxThread → 返回抽象接口指针给上层。
控制流:配置解析器 → 工厂选择器 → 调用具体工厂的构造方法 → 完成产品族初始化。
信任链路:Framework 核心信任抽象产品接口契约;平台适配层信任具体工厂返回的对象满足接口语义;具体产品信任底层系统调用正确实现。

3.6 内联 SVG:抽象工厂平台适配层结构

抽象工厂平台适配层结构 Framework 核心 抽象工厂 AdaptorFactory 配置解析器 LinuxAdaptorFactory ZephyrAdaptorFactory 抽象产品 Thread 抽象产品 Mutex 抽象产品 FileSystem 具体产品族(Linux产品族 / Zephyr产品族) LinuxThread PthreadMutex LinuxFileSystem

3.7 选型权衡

方案优点缺点
抽象工厂模式产品族统一约束,新增平台只需添加具体工厂类,符合开闭原则产品族扩展需修改抽象工厂接口(违反开闭),多层继承增加代码量
工厂方法 + 模板特化避免抽象工厂接口膨胀,编译期多态性能好运行时动态切换困难,模板错误信息晦涩
配置+if-else链实现简单,适合平台数量 ≤3 的场景违反开闭原则,平台增加导致代码膨胀,难以维护

推荐场景:平台数 ≥3 且产品族稳定(如嵌入式 RTOS + Linux + 裸机)时优先使用抽象工厂模式;短期原型可用配置+if-else 快速验证。

3.8 风险点

风险 1:产品族约束泄露——具体工厂返回的对象可能不符合抽象接口约定,例如 Linux 下的 Mutex 实现依赖了线程优先级排序,而 Zephyr 的互斥量不支持。解决:增加集成测试用例覆盖每个产品的边界语义。
风险 2:配置错误导致工厂选择失败——运行时不存在的平台字符串会导致空指针或未定义行为。解决:提供工厂注册表(Registry)并启用静态断言检查。
风险 3:二进制体积膨胀——同时编译所有具体工厂可能增大 ROM 占用。解决:使用条件编译 + 链接时优化排除未用符号。

3.9 落地步骤

  1. 定义抽象产品接口(Thread、Mutex、FileSystem)并编写单元测试桩。
  2. 创建抽象工厂基类 PlatformAdaptor,声明纯虚创建方法。
  3. 为每个目标平台实现具体工厂类(LinuxAdaptor、ZephyrAdaptor)。
  4. 实现配置解析器(编译时或运行时),绑定工厂选择逻辑。
  5. 在 Framework 核心初始化阶段调用工厂获取产品族实例。
  6. 在 CI 中增加多平台编译、链接及功能集成测试。

3.10 验收标准

  • 支持至少两种异构平台(如 Linux + Zephyr)的无缝切换,仅通过配置变更触发。
  • 上层代码无需包含任何平台相关的 #ifdef 或系统头文件。
  • 若配置指定非法平台,编译期报错(静态配置)或返回 nullptr 且日志记录(动态配置)。
  • 新增第三个平台时,无需修改任何已有抽象产品接口或 Framework 核心代码(仅需新增具体工厂类并注册)。
  • 产品族内部各对象之间的互操作正确性通过集成测试验证(例如 Thread 创建后协程切换不与 Mutex 死锁)。