当前位置: 首页 > article >正文

使用单例模式+观察者模式实现参数配置实时更新

使用vector存储观察者列表

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>

// 配置参数结构体
struct MyConfigStruct {
    int parameter1;
    std::string parameter2;
};

class Config {
public:
    using Observer = std::function<void(const MyConfigStruct&)>;

    static Config& getInstance() {
        static Config instance;
        return instance;
    }

    // 注册观察者
    void registerObserver(Observer observer) {
        observers_.push_back(observer);
    }

    // 移除观察者
    void removeObserver(Observer observer) {
        observers_.erase(std::remove_if(observers_.begin(), observers_.end(),
            [observer](const Observer& o) {
                return o.target_type() == observer.target_type();
            }), observers_.end());
    }
    /*
    void removeObserver(Observer observer) {
 auto it = std::find_if(observers_.begin(), observers_.end(),
            [observer](const Observer& o) {
                return &o == &observer;
            });
        if (it != observers_.end()) {
            observers_.erase(it);
        }

    }*/
    // Setter方法用于修改配置参数的值
    void setParameters(const MyConfigStruct& newParameters) {
        parameters_ = newParameters;
        notifyObservers();
    }

private:
    Config() {
        // 初始化配置参数
        parameters_ = { 0, "" };
    }

    // 配置参数
    MyConfigStruct parameters_;

    // 观察者集合
    std::vector<Observer> observers_;

    // 通知观察者
    void notifyObservers() {
        for (const auto& observer : observers_) {
            observer(parameters_);
        }
    }
};

// 模块A作为观察者,处理参数变化的通知
class ModuleA {
public:
    void handleConfigUpdate(const MyConfigStruct& config) {
        std::cout << "Module A: Parameter 1 = " << config.parameter1 << ", Parameter 2 = " << config.parameter2 << std::endl;
    }
};

// 模块B作为观察者,处理参数变化的通知
class ModuleB {
public:
    void handleConfigUpdate(const MyConfigStruct& config) {
        std::cout << "Module B: Parameter 1 = " << config.parameter1 << ", Parameter 2 = " << config.parameter2 << std::endl;
    }
};

int main() {
    // 创建配置实例和模块实例
    Config& config = Config::getInstance();
    ModuleA moduleA;
    ModuleB moduleB;

    // 注册观察者
    config.registerObserver([&moduleA](const MyConfigStruct& config) {
        moduleA.handleConfigUpdate(config);
    });
    config.registerObserver([&moduleB](const MyConfigStruct& config) {
        moduleB.handleConfigUpdate(config);
    });

    // 更新配置参数
    MyConfigStruct newParameters{ 42, "Hello World" };
    config.setParameters(newParameters);

    // 移除观察者
    config.removeObserver([&moduleA](const MyConfigStruct& config) {
        moduleA.handleConfigUpdate(config);
    });

    // 再次更新配置参数
    MyConfigStruct newParameters2{ 100, "Goodbye" };
    config.setParameters(newParameters2);

    return 0;
}

输出结果

Module A: Parameter 1 = 42, Parameter 2 = Hello World
Module B: Parameter 1 = 42, Parameter 2 = Hello World
Module A: Parameter 1 = 100, Parameter 2 = Goodbye
Module B: Parameter 1 = 100, Parameter 2 = Goodbye

removeObserver 方法中,我们使用了 std::remove_if 来查找并移除与指定观察者对象类型相同的观察者。通过比较 o.target_type()observer.target_type() 可以判断两个观察者对象的类型是否相同。
在 C++ 中,std::function 是一个通用的函数封装器,可以包装任意可调用对象(如函数指针、函数对象、Lambda 表达式等)。为了允许运行时检查 std::function 所包装的具体函数对象类型,C++ 提供了 target_type() 成员函数来获取存储的函数对象类型信息。

在上述代码中,我们使用 o.target_type()observer.target_type() 来比较两个观察者对象的函数对象类型是否相同。这样做是为了确保移除与指定观察者对象类型相同的观察者。

请注意,target_type() 返回的是 std::type_info 对象的指针,而不是直接的类型。因此,我们使用 == 运算符来比较两个 std::type_info 对象的指针是否相等,以判断两个观察者对象的函数对象类型是否相同。

使用set存储观察者列表

#include <iostream>
#include <set>
#include <functional>

// 配置参数结构体
struct MyConfigStruct {
    int parameter1;
    std::string parameter2;
};

class Config {
public:
    using Observer = std::function<void(const MyConfigStruct&)>;

    static Config& getInstance() {
        static Config instance;
        return instance;
    }

    // 注册观察者
    void registerObserver(Observer observer) {
        observers_.insert(observer);
    }

    // 移除观察者
    void removeObserver(Observer observer) {
        observers_.erase(observer);
    }

    // Setter方法用于修改配置参数的值
    void setParameters(const MyConfigStruct& newParameters) {
        parameters_ = newParameters;
        notifyObservers();
    }

private:
    Config() {
        // 初始化配置参数
        parameters_ = { 0, "" };
    }

    // 配置参数
    MyConfigStruct parameters_;

    // 比较函数对象,用于在集合中排序观察者
    struct ObserverComparator {
        bool operator()(const Observer& lhs, const Observer& rhs) const {
            // 在这里实现你需要的比较逻辑
            // 这里简单地使用内存地址进行比较
            return &lhs < &rhs;
        }
    };

    // 观察者集合
    std::set<Observer, ObserverComparator> observers_;

    // 通知观察者
    void notifyObservers() {
        for (const auto& observer : observers_) {
            observer(parameters_);
        }
    }
};

// 模块A作为观察者,处理参数变化的通知
class ModuleA {
public:
    void handleConfigUpdate(const MyConfigStruct& config) {
        std::cout << "Module A: Parameter 1 = " << config.parameter1 << ", Parameter 2 = " << config.parameter2 << std::endl;
    }
};

// 模块B作为观察者,处理参数变化的通知
class ModuleB {
public:
    void handleConfigUpdate(const MyConfigStruct& config) {
        std::cout << "Module B: Parameter 1 = " << config.parameter1 << ", Parameter 2 = " << config.parameter2 << std::endl;
    }
};

int main() {
    // 创建配置实例和模块实例
    Config& config = Config::getInstance();
    ModuleA moduleA;
    ModuleB moduleB;

    // 注册观察者
    config.registerObserver([&moduleA](const MyConfigStruct& config) {
        moduleA.handleConfigUpdate(config);
    });
    config.registerObserver([&moduleB](const MyConfigStruct& config) {
        moduleB.handleConfigUpdate(config);
    });

    // 更新配置参数
    MyConfigStruct newParameters{ 42, "Hello World" };
    config.setParameters(newParameters);

    // 移除观察者
    config.removeObserver([&moduleA](const MyConfigStruct& config) {
        moduleA.handleConfigUpdate(config);
    });

    // 再次更新配置参数
    MyConfigStruct newParameters2{ 100, "Goodbye" };
    config.setParameters(newParameters2);

    return 0;
}

同样的输出结果

Module A: Parameter 1 = 42, Parameter 2 = Hello World
Module B: Parameter 1 = 42, Parameter 2 = Hello World
Module A: Parameter 1 = 100, Parameter 2 = Goodbye
Module B: Parameter 1 = 100, Parameter 2 = Goodbye

在上述代码中,ObserverComparator 是一个用于比较观察者对象的比较器结构体。它实现了一个 operator() 函数,该函数接受两个观察者对象作为参数,并返回一个布尔值来表示它们的相对顺序。

在这个比较器中,我们简单地使用观察者对象的内存地址进行比较。如果 &lhs 小于 &rhs,则认为 lhs 在集合中应该排在 rhs 的前面,返回 true。否则,返回 false

通过使用自定义的比较器,我们可以在 std::set 中根据指定的比较逻辑对观察者进行排序。这样做可以确保观察者在集合中以特定的顺序存储,并且在通知观察者时按照指定的顺序进行遍历。

需要注意的是,由于比较的是观察者对象的地址而不是函数对象本身,因此在使用这种比较器时需要小心。确保观察者对象的生命周期足够长,以便比较其地址的有效性。


http://www.kler.cn/news/161904.html

相关文章:

  • 算术运算(这么简单?进来坐坐?)
  • 复杂gRPC之go调用go
  • C++标准模板(STL)- 类型支持 (杂项变换,确定一组类型的公共类型,std::common_type)
  • C#-using处理非托管资源
  • 我不是DBA之慢SQL诊断方式
  • 云原生之深入解析Kubernetes策略引擎对比:OPA/Gatekeeper与Kyverno
  • 【React】路由的基础使用
  • SpringAOP专栏一《使用教程篇》
  • 学习Opencv(蝴蝶书/C++)相关1——4.图形和大型数组类型
  • Java String相关问题
  • StringBoot常用注解(不断添加)
  • ncnn模型部署——使用VS2019把项目打包成DLL文件
  • 【头歌实训】分布式文件系统 HDFS
  • 火狐,要完了!
  • GateWay网关介绍以及整合knife4j聚合所有服务的接口文档
  • pymol使用
  • EI级 | Matlab实现TCN-GRU-Multihead-Attention多头注意力机制多变量时间序列预测
  • TE发布最新TC Policy 3.1
  • 单片机第三季-第四课:STM32下载、MDK和调试器
  • 网站建设app开发小程序制作|企业软件定制
  • 有爱的冬天不再冷——壹基金儿童温暖包抵达富平
  • Kubernetes(K8s)Pod控制器详解-06
  • Java的List中的各种浅拷贝和深拷贝问题
  • 超大规模集成电路设计----FPGA时序模型及FSM的设计(八)
  • 查看端口号是否被占用
  • 指针数组和数组指针作为形式参数
  • SmartChart:一站式数据可视化解决方案
  • SpringBoot:SpringMVC(上)
  • 2023-12-04 AIGC-Stable Diffusion和SadTalker-搭建及使用
  • Linux_CentOS_7.9 VNC安装卸载以及相关配置开机自启动服务简易记录