多主题多订阅者的情况怎样处理比较好?

探讨在多主题多订阅者场景下Observer模式的应用挑战。如何在降低耦合度的同时避免资源浪费,特别是在拥有数十个主题的复杂系统中。
在单主题多订阅者的情况,就是用Observer模式了。

但是对于多主题多订阅者,如果对于每一个主题的更新,模型都要清楚的知道哪些订阅者订阅了这个主题,这样的耦合度是不是太高了?但是如果不这样的话,那么一个主题的更新,就带来所有订阅者的更新——无论这个订阅者是否订阅了这个主题,这又是很大的浪费把?

比如在一个模型中,有主题A,B,C,订阅者有a,b,c,d,其中a,b订阅A,b,c订阅B,a,c,d订阅C,或者主题再多上一些,有几十个的话,这时候怎样设计比较好呢?
在 OpenDDS 中,订阅者(Subscriber)可以处理主题(Topic)的机制主要依赖于其灵活的发布-订阅架构和数据分发服务(DDS)标准的支持。通过合理配置和使用 OpenDDS 的 API,可以实现一个订阅者监听主题处理不同数据流的需求。 ### 1. 使用个数据读取器(DataReader) 订阅者可以通过创建个数据读取器实例,每个实例绑定到一个特定的主题。这样,每个数据读取器可以独立地接收和处理其对应主题的数据。 ```cpp // 创建主题 DDS::Topic_var topic1 = participant->create_topic("Topic1", type_name1, TOPIC_QOS_DEFAULT, NULL, DDS::STATUS_MASK_NONE); DDS::Topic_var topic2 = participant->create_topic("Topic2", type_name2, TOPIC_QOS_DEFAULT, NULL, DDS::STATUS_MASK_NONE); // 创建个数据读取器 DDS::DataReader_var reader1 = subscriber->create_datareader(topic1, DATAREADER_QOS_DEFAULT, NULL, DDS::STATUS_MASK_ALL); DDS::DataReader_var reader2 = subscriber->create_datareader(topic2, DATAREADER_QOS_DEFAULT, NULL, DDS::STATUS_MASK_ALL); ``` 上述代码展示了如何为两个不同的主题创建数据读取器。每个数据读取器都可以注册一个独立的回调函数,用于处理各自主题的数据[^3]。 ### 2. 使用单一数据读取器监听主题 另一种方法是使用单一的数据读取器监听主题。这可以通过设置主题表达式(Topic Expression)来实现,适用于主题名称具有某种模式的情况。 ```cpp // 使用主题表达式创建主题 DDS::TopicDescription_var topic_desc = participant->lookup_topicdescription("Topic*"); DDS::DataReader_var reader = subscriber->create_datareader(topic_desc, DATAREADER_QOS_DEFAULT, NULL, DDS::STATUS_MASK_ALL); ``` 在这种配置下,数据读取器将监听所有匹配 `Topic*` 模式的主题。需要注意的是,这种方法要求所有主题具有相同的类型定义[^2]。 ### 3. 使用内容过滤器(Content Filter) OpenDDS 还支持使用内容过滤器来实现更复杂的数据筛选机制。通过配置内容过滤器,订阅者可以基于数据内容选择性地接收特定主题中的数据。 ```cpp // 创建带内容过滤器的主题 DDS::Topic_var topic = participant->create_topic("MyTopic", type_name, TOPIC_QOS_DEFAULT, NULL, DDS::STATUS_MASK_NONE); DDS::ContentFilteredTopic_var cft = participant->create_contentfilteredtopic("FilteredTopic", topic, "x > 10", DDS::StringSeq()); DDS::DataReader_var reader = subscriber->create_datareader(cft, DATAREADER_QOS_DEFAULT, NULL, DDS::STATUS_MASK_ALL); ``` 上述代码展示了如何为 `MyTopic` 主题创建一个内容过滤器,仅接收 `x > 10` 的数据样本[^2]。 ### 4. 使用模块化设计 在实际应用中,建议将每个主题处理逻辑模块化。可以为每个主题创建独立的处理类或函数,确保代码结构清晰、易于维护。 ```cpp class Topic1Handler { public: void on_data_available(DDS::DataReader_ptr reader); }; class Topic2Handler { public: void on_data_available(DDS::DataReader_ptr reader); }; ``` 每个类可以实现 `on_data_available` 方法,用于处理各自主题的数据。这种方式有助于提高代码的可扩展性和可测试性[^1]。 ### 5. 配置 QoS 策略 OpenDDS 支持丰富的 QoS 策略配置,可以根据需求为每个主题设置不同的 QoS 参数。例如,可以为实时性要求高的主题配置较低的传输延迟。 ```cpp DDS::DataReaderQos dr_qos; participant->get_default_datareader_qos(dr_qos); dr_qos.reliability.kind = DDS::RELIABLE_RELIABILITY_QOS; dr_qos.durability.kind = DDS::TRANSIENT_LOCAL_DURABILITY_QOS; // 应用 QoS 到数据读取器 subscriber->create_datareader(topic, dr_qos, NULL, DDS::STATUS_MASK_ALL); ``` 上述代码展示了如何配置数据读取器的 QoS 策略,确保数据的可靠性和持久性。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值