DAB实现中用到的主要设计模式

DAB C++ 版本设计模式应用实践

1. 命令模式 (Command Pattern)

设计目标

  • 模块解耦:实现各模块独立编译、测试、运行,消除模块间直接依赖
  • 扩展准备:为桥接模式实现奠定基础
  • 依赖倒置:通过命令对象反转模块依赖方向
  • 耦合降低:将模块间耦合简化为命令对象耦合

1.1 MQTT 模块实现

cpp 复制代码
#pragma once
#include <string>
#include <vector>
#include <functional>

/**
 * @class HiMqttClient
 * @brief MQTT 客户端核心类,提供连接管理、消息发布订阅等功能
 * 
 * @note 采用命令模式实现消息处理回调机制
 */
class HiMqttClient {
public:
    // 连接管理接口
    static void start(const char* ip, int port, const char* user, 
                     const char* password, const char* clientId);
    static void stop();

    // 消息管理接口
    static void subscribe(const std::vector<std::string>& topics);
    static bool publish(const char* topic, const char* body);

    // 命令模式回调设置
    static void onTopic(const std::function<void(const char*, const char*, 
                                const char*, const char*)>& func);
};

设计亮点

  • 通过 onTopic() 设置命令对象实现消息处理解耦
  • 支持模块独立单元测试
  • 消除与其他业务模块的循环依赖

1.2 Topic 处理器实现

#pragma once
#include <map>
#include <functional>
#include "context/dab_context.h"

/**
 * @class TopicHandler
 * @brief 基于命令模式的主题处理器
 * 
 * @note 使用注册机制替代传统 switch-case 分支处理
 */
class TopicHandler {
public:
    // 生命周期管理
    static void init(int maxThreads);
    static void destroy();

    // 命令注册接口
    static void registerHandler(const std::map<std::string, 
        std::function<void(DABContext&)>>& handles);

    // 统一消息入口
    static void onTopic(const char* topic, const char* body,
                      const char* response_topic, const char* correlation_data);
};

创新点

  • 动态注册机制实现处理逻辑可配置化
  • 统一消息入口简化调用链路
  • 天然支持多线程处理

1.3 上下文对象设计

#pragma once
#include "context/dab_status.h"
#include "context/dab_request.h"
#include "context/dab_response.h"

/**
 * @class DABContext
 * @brief 请求处理上下文对象
 * 
 * @note 采用命令模式封装消息发布功能
 */
class DABContext {
public:
    // 状态管理接口
    bool is_ok() const;
    void success();
    void clientFail(const char* out_log, const char* inner_log = nullptr);

    // 消息发布命令接口
    static void setPublishFunc(const std::function<void(const char*, const char*)>& func);
    static void publish(DABContext& context);
    
    // 数据成员
    DABStatus status;
    DABRequest request;
    DABResponse response;
};

技术优势

  • 隐藏 MQTT 实现细节
  • 支持多种消息发布策略
  • 上下文自包含设计简化单元测试

1.4 日志模块实现

#pragma once

#include <functional>

/**
 * @enum DABLogLevel
 * @brief 日志级别枚举定义
 */
enum class DABLogLevel { INFO, WARNING, ERROR, FATAL, ALWAYS };

namespace dab {
    /**
     * @brief 日志回调设置接口
     * @param callback 日志处理函数原型:
     *        void(日志级别, 文件名, 函数名, 行号, 日志内容)
     */
    void set_log_callback(std::function<void(DABLogLevel, const char*, 
                           const char*, int, const char*)> callback);

    // 日志宏定义
    #define DABLOG_INFO(...)  dab::writeLog(DABLogLevel::INFO, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
    #define DAB_ASSERT(expr, desc) \
        do { if (!(expr)) { \
            dab::on_assert_fail(__FILE__, __FUNCTION__, __LINE__); \
        }} while(0)
}

核心价值

  • 灵活适配不同日志实现
  • 支持运行时日志策略切换
  • 提供丰富的调试信息

2. 桥接模式 (Bridge Pattern)

设计目标

  • 架构解耦:分离抽象与具体实现
  • 独立演进:各模块可独立变化
  • 统一接口:提供标准化服务能力

系统桥接实现

void publish(const char* topic, const char* body) {
    HiMqttClient::publish(topic, body);     
}

extern "C" int runDabService() {
    // 初始化各模块
    TopicHandler::init(DABProperties::max_handle_threads);
    DABHandler::init();
    
    // 桥接关键点
    HiMqttClient::onTopic(TopicHandler::onTopic);
    DABContext::setPublishFunc(publish);

    // 订阅与注册
    HiMqttClient::subscribe(DABHandler::getTopics());
    TopicHandler::registerHandler(DABHandler::getTopicHandles());

    // 启动服务
    HiMqttClient::start(DABProperties::mqtt_ip.c_str(), 
                      DABProperties::mqtt_port, ...);
    return 0;
}

桥接优势

  • 业务逻辑与通信协议解耦
  • 模块间通过抽象接口通信
  • 新增协议支持成本最低化

3. 适配器模式 (Adapter Pattern)

设计目标

  • 接口标准化:统一不同系统的接口规范
  • 依赖倒置:反转系统接口依赖方向
  • 扩展支持:为策略模式实施奠定基础

典型应用

  1. 日志适配器:将系统日志接口转换为 DAB 标准日志接口
  2. 服务适配:封装平台特性接口为统一服务接口

适配收益

  • 业务代码不依赖具体实现
  • 新增平台支持只需实现适配器
  • 保持核心逻辑稳定性

4. 策略模式 (Strategy Pattern)

应用场景

场景 实现策略 优势
电视环境 真实硬件接口实现 完整功能支持
云端环境 Mock 接口实现 无硬件依赖的自动化测试
单元测试 内存型轻量实现 快速测试执行

策略配置

cpp 复制代码
    // 测试环境初始化示例
    void dabInit() {
        DABContext::setPublishFunc([](const char* t, const char* b) {
            DABLOG_ALWAYS("Test Publish: %s -> %s", t, b);
        });
        
        TopicHandler::registerHandler({
            {"test/topic1", [](DABContext& ctx){ /* Mock处理逻辑 */ }},
            {"test/topic2", [](DABContext& ctx){ /* Mock处理逻辑 */ }}
        });
    }

策略优势

  • 运行时动态切换实现
  • 环境隔离保证测试可靠性
  • 并行支持多种部署方案

5.单例模式

在DAB的实现中,有意回避了单例模式,使用静态类代替。

```cpp

    class TopicHandler {
    public:
    static void init(int maxThreads);   // 显式初始化
    static void destroy();              // 显式资源释放
    static void registerHandler(/*...*/);
    TopicHandler() = delete;            // 禁止实例化
    };

```

**设计考量**:
1.  **生命周期可控**:通过`init()`/`destroy()`明确管理资源
2.  **测试友好**:支持不同测试用例的独立初始化
3.  **避免全局状态**:每个模块维护自身静态数据
4.  **编译期约束**:`= delete`禁止非法操作
    **对比传统单例**:
*   不强制全局唯一实例
*   无隐式初始化顺序问题
*   支持多环境配置(测试/生产)

6. 测试体系设计

1. 测试环境搭建

cpp 复制代码
#include <gtest/gtest.h>
#include "dab/dab_api.h"

// 全局测试环境类
class TestEnv : public testing::Environment {
public:
    void SetUp() override { dabInit(); }    // 测试用例初始化
    void TearDown() override { dabDestory(); } // 测试资源回收
};

// 核心初始化逻辑
namespace {
    // 模拟消息发布函数
    void publish(const char* topic, const char* body) {
        DABLOG_ALWAYS("[TEST] Topic:%s\nPayload:%s", topic, body);
    }

    void dabInit() {
        DABProperties::device_id = "TEST_DEVICE"; // 设置测试设备ID
        TopicHandler::init(5);    // 初始化消息处理线程池
        DABHandler::init();       // 业务处理器初始化
        DABContext::setPublishFunc(publish); // 注入模拟发布器
        
        // 注册Topic处理函数
        TopicHandler::registerHandler(DABHandler::getTopicHandles());
    }

    void dabDestory() {
        TopicHandler::destroy();  // 清理消息处理器
        DABHandler::destroy();    // 清理业务处理器
    }
}

// 测试主入口
int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    testing::AddGlobalTestEnvironment(new TestEnv);
    return RUN_ALL_TESTS();
}

2. 设计模式应用解析

设计模式 应用场景 实现要点
命令模式 消息处理函数注册 通过registerHandler注册处理闭包
桥接模式 业务处理与MQTT通信解耦 setPublishFunc实现协议隔离
策略模式 测试环境与生产环境配置切换 DABProperties动态配置

3.测试辅助工具实现

1. Topic处理工具类

namespace {
    // 生成标准Topic格式
    std::string formatTopic(const std::string& baseTopic) {
        std::ostringstream oss;
        oss << "dab/" << DABProperties::device_id << "/" << baseTopic;
        return oss.str();
    }
}

// 统一测试入口函数
void onTopicTest(const std::string& topic, const std::string& request) {
    TopicHandler::onTopic(
        formatTopic(topic).c_str(),  // 格式化请求Topic
        request.c_str(),             // 测试请求载荷
        "_response/" + formatTopic(topic).c_str(), // 响应Topic
        ""                           // 关联数据
    );
}

2. 工具类设计亮点

  1. Topic规范化:自动添加设备ID前缀
  2. 响应隔离:生成专用的响应Topic通道
  3. 异常防护:内置空指针检查等安全机制
  4. 日志追踪:自动记录测试消息流向

4.应用功能测试案例

1. 应用管理测试集

TEST(DABHandler, ApplicationManagement) {
    // 基础功能测试
    onTopicTest("applications/list", "{}"); // 空参数查询
    
    // 典型场景测试
    onTopicTest("applications/launch", 
        R"({"appId":"YouTube"})"); // 标准应用启动
    
    // 带参数启动测试
    onTopicTest("applications/launch", 
        R"({
            "appId": "Netflix",
            "parameters": [
                "-KEY", 
                "https%3A%2F%2Fwww.example.com%2F",
                "-STANDALONE_PARAM"
            ]
        })");
    
    // 状态管理测试
    onTopicTest("applications/get-state", 
        R"({"appId":"YouTube"})");
    
    // 退出机制测试
    onTopicTest("applications/exit", 
        R"({"appId":"YouTube"})"); // 常规退出
    onTopicTest("applications/exit", 
        R"({"appId":"YouTube","background":true})"); // 后台退出
}
相关推荐
Cikiss3 小时前
「全网最细 + 实战源码案例」设计模式——桥接模式
java·后端·设计模式·桥接模式
纪元A梦4 小时前
Java设计模式:行为型模式→观察者模式
java·观察者模式·设计模式
荣--17 小时前
回顾我的软件开发经历:开发DAB
c++·单元测试·项目管理·nodejs·dab·多平台支持·正交性原则
mofei1213819 小时前
Python设计模式 - 组合模式
python·设计模式·组合模式
小王子10241 天前
设计模式Python版 抽象工厂模式
python·设计模式·抽象工厂模式
利刃大大1 天前
【C++】设计模式详解:单例模式
c++·单例模式·设计模式
小小工匠1 天前
设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用
设计模式·模板方法模式
电子科技圈1 天前
智能化加速标准和协议的更新并推动验证IP(VIP)在芯片设计中的更广泛应用
经验分享·科技·嵌入式硬件·设计模式
SomeB1oody1 天前
【Rust自学】17.3. 实现面向对象的设计模式
开发语言·设计模式·rust