Procházet zdrojové kódy

#添加观察者模式

zxs před 2 týdny
rodič
revize
7cb645719f

+ 10 - 11
message_bus/message_bus_impl.cpp

@@ -13,23 +13,22 @@ namespace robotics::v3 {
 		return &g_message_bus_impl;
 	}
 
-	bool message_bus_impl::bind(std::string const& str_topic, std::any const& fn) {
+	bool message_bus_impl::bind(std::string const& str_topic, bool observer, std::any const& fn) {
 		auto range = map_.equal_range(str_topic);
-		if (range.first != range.second)
-			return false;
-		map_.emplace(str_topic, std::pair(false, fn));
+		for (Iterater it = range.first; it != range.second; ++it) {
+			if (it->second.first == false && !observer) {
+				return false;
+			}
+		}
+		map_.emplace(str_topic, std::pair(observer, fn));
 		return true;
 	}
 
-	void message_bus_impl::bind_multiple(std::string const& str_topic, std::any const& fn) {
-		map_.emplace(str_topic, std::make_pair(true, fn));
-	}
-
-	std::vector<std::any> message_bus_impl::find(const std::string& str_topic) {
-		std::vector<std::any> result;
+	std::vector<std::pair<bool, std::any>> message_bus_impl::find(const std::string& str_topic) {
+		std::vector<std::pair<bool, std::any>> result;
 		auto range = map_.equal_range(str_topic);
 		for (Iterater it = range.first; it != range.second; ++it) {
-			result.push_back(it->second.second);
+			result.push_back(it->second);
 		}
 		return result;
 	}

+ 7 - 12
message_bus/message_bus_impl.h

@@ -26,24 +26,19 @@ namespace robotics::v3 {
 		static message_bus_impl* instance();
 		~message_bus_impl();
 		/**
-		 * @brief 绑定单个函数
-		 * @param str_topic
-		 * @param fn
-		 * @return
-		 */
-		bool bind(std::string const& str_topic, std::any const& fn);
-		/**
-		 * @brief 绑定多个函数
-		 * @param str_topic
-		 * @param fn
+		 * @brief 函数绑定到指定主题。
+		 * @param str_topic 要绑定的主题名称。
+		 * @param observer 指示是否作为观察者绑定的布尔值。
+		 * @param fn 要绑定的函数对象。
+		 * @return 如果绑定成功则返回 true,否则返回 false。
 		 */
-		void bind_multiple(std::string const& str_topic, std::any const& fn);
+		bool bind(std::string const& str_topic, bool observer, std::any const& fn);
 		/**
 		 * @brief 查找
 		 * @param str_topic 
 		 * @return 
 		 */
-		std::vector<std::any> find(const std::string& str_topic);
+		std::vector<std::pair<bool, std::any>> find(const std::string& str_topic);
 		/**
 		 * @brief 删除
 		 * @param str_topic 

+ 46 - 58
robot/robotics/message_bus.hpp

@@ -36,71 +36,60 @@ namespace robotics {
 			}
 			/**
 			 * @brief 注册消息
-			 * @tparam _Fn
-			 * @param str_topic
-			 * @param f
-			 */
-			template<typename _Fn>
-			void bind_multiple(const std::string& str_topic, _Fn&& f) {
-				auto func = v3::to_function(std::forward<_Fn>(f));
-				add_multiple(str_topic, std::move(func));
-			}
-			/**
-			 * @brief 注册消息
-			 * @tparam _Fn
-			 * @tparam _Obj
-			 * @param str_topic
-			 * @param f
-			 * @param obj
-			 */
-			template<typename _Fn, typename _Obj>
-			void bind_multiple(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
-				auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
-				add_multiple(str_topic, std::move(func));
-			}
-			/**
-			 * @brief 注册消息
-			 * @tparam _Fn
-			 * @param str_topic
-			 * @param f
+			 * @tparam _Fn 
+			 * @param str_topic 
+			 * @param observer 观察者
+			 * @param f 
+			 * @return 
 			 */
 			template<typename _Fn>
-			bool bind(const std::string& str_topic, _Fn&& f) {
+			bool bind(const std::string& str_topic, bool observer, _Fn&& f) {
 				auto func = v3::to_function(std::forward<_Fn>(f));
-				return add(str_topic, std::move(func));
+				return add(str_topic, observer, std::move(func));
 			}
 			/**
 			 * @brief 注册消息
-			 * @tparam _Fn
-			 * @tparam _Obj
-			 * @param str_topic
-			 * @param f
-			 * @param obj
+			 * @tparam _Fn 
+			 * @tparam _Obj 
+			 * @param str_topic 
+			 * @param observer 观察者
+			 * @param f 
+			 * @param obj 
+			 * @return 
 			 */
 			template<typename _Fn, typename _Obj>
-			bool bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
+			bool bind(const std::string& str_topic, bool observer, _Fn&& f, _Obj&& obj) {
 				auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
-				return add(str_topic, std::move(func));
+				return add(str_topic, observer, std::move(func));
 			}
 			/**
 			 * @brief 发送消息
 			 * @param str_topic
 			 */
-			template<typename _Ret>
+			template<typename _Ret,typename _BCast>
 			_Ret invoke(const std::string& str_topic) {
 				using function_type = std::function<_Ret()>;
 				std::string str_msg_type = str_topic + typeid(function_type).name();
 				auto funcs = message_bus_impl_->find(str_msg_type);
-				if constexpr(std::is_same<_Ret, void>::value) {
-					for(auto &fn : funcs) {
-						std::any_cast<function_type>(fn)();
-					}
-				} else {
-					if (funcs.empty())
+				if constexpr (!_BCast) {
+					if (std::find_if(funcs.begin(), funcs.end(), [](auto it) {return !it.first; }) == funcs.end()) {
 						throw std::runtime_error("no function binded to topic " + str_topic);
+					}
+				}
+				if constexpr (std::is_same<_Ret, void>::value) {
+					for (auto& fn : funcs) {
+						std::any_cast<function_type>(fn.second)();
+					}
+				}
+				else {
 					_Ret result = _Ret{};
-					for(auto &fn : funcs) {
-						result = std::any_cast<function_type>(fn)();
+					for (auto& fn : funcs) {
+						if (!fn.first) {
+							result = std::any_cast<function_type>(fn.second)();
+						}
+						else {
+							std::any_cast<function_type>(fn.second)();
+						}
 					}
 					return result;
 				}
@@ -111,11 +100,16 @@ namespace robotics {
 			 * @param str_topic
 			 * @param ...args
 			 */
-			template<typename _Ret,typename... _Args>
+			template<typename _Ret, typename _BCast,typename... _Args>
 			_Ret invoke(const std::string& str_topic, _Args ...args) {
 				using function_type = std::function<_Ret(_Args...)>;
 				std::string str_msg_type = str_topic + typeid(function_type).name();
 				auto funcs = message_bus_impl_->find(str_msg_type);
+				if constexpr (!_BCast) {
+					if (std::find_if(funcs.begin(), funcs.end(), [](auto it) {return !it.first; }) == funcs.end()) {
+						throw std::runtime_error("no function binded to topic " + str_topic);
+					}
+				}
 				if constexpr(std::is_same<_Ret, void>::value) {
 					for(auto &fn : funcs) {
 						std::any_cast<function_type>(fn)(args...);
@@ -126,7 +120,12 @@ namespace robotics {
 						throw std::runtime_error("no function binded to topic " + str_topic);
 					_Ret result = _Ret{};
 					for (auto& fn : funcs) {
-						result = std::any_cast<function_type>(fn)(args...);
+						if (!fn.first) {
+							result = std::any_cast<function_type>(fn.second)(args...);
+						}
+						else {
+							std::any_cast<function_type>(fn.second)(args...);
+						}
 					}
 					return result;
 				}
@@ -143,17 +142,6 @@ namespace robotics {
 				message_bus_impl_->remove(str_msg_type);
 			}
 		private:
-			/**
-			 * @brief 多个添加
-			 * @tparam _Fn
-			 * @param str_topic
-			 * @param f
-			 */
-			template<typename _Fn>
-			void add_multiple(const std::string& str_topic, _Fn&& f) {
-				std::string str_msg_type = str_topic + typeid(f).name();
-				message_bus_impl_->bind_multiple(str_msg_type, std::forward<_Fn>(f));
-			}
 			/**
 			 * @brief 单个添加
 			 * @tparam _Fn 

+ 8 - 13
robot/robotics/message_bus_impl.h

@@ -26,24 +26,19 @@ namespace robotics::v3 {
 		static message_bus_impl* instance();
 		~message_bus_impl();
 		/**
-		 * @brief 绑定单个函数
-		 * @param str_topic
-		 * @param fn
-		 * @return
-		 */
-		bool bind(std::string const& str_topic, std::any const& fn);
-		/**
-		 * @brief 绑定多个函数
-		 * @param str_topic
-		 * @param fn
+		 * @brief 函数绑定到指定主题。
+		 * @param str_topic 要绑定的主题名称。
+		 * @param observer 指示是否作为观察者绑定的布尔值。
+		 * @param fn 要绑定的函数对象。
+		 * @return 如果绑定成功则返回 true,否则返回 false。
 		 */
-		void bind_multiple(std::string const& str_topic, std::any const& fn);
+		bool bind(std::string const& str_topic, bool observer, std::any const& fn);
 		/**
 		 * @brief 查找
 		 * @param str_topic
 		 * @return
 		 */
-		std::vector<std::any> find(const std::string& str_topic);
+		std::vector<std::pair<bool, std::any>> find(const std::string& str_topic);
 		/**
 		 * @brief 删除
 		 * @param str_topic
@@ -55,4 +50,4 @@ namespace robotics::v3 {
 		std::multimap<std::string, std::pair<bool, std::any>> map_;
 		typedef std::multimap<std::string, std::pair<bool, std::any>>::iterator Iterater;
 	};
-	}
+}