设计模式之观察者与策略:面试官问“ROS2回调机制用的什么模式”,我没答上来

发布时间:2026/7/17 5:44:14
设计模式之观察者与策略:面试官问“ROS2回调机制用的什么模式”,我没答上来 上篇聊了单例和工厂模式今天继续设计模式专题聊聊观察者模式和策略模式。这两个模式在机器人开发里特别常见——ROS2的回调机制就是观察者模式机器人的行为切换就是策略模式。但面试的时候很多人知道怎么用却说不出背后的设计模式。面试官问ROS2的回调机制用的什么设计模式如果你能直接回答观察者模式并且讲清楚为什么面试官对你的评价会高一个档次。观察者模式发布-订阅的本质观察者模式的定义对象之间一对多的依赖关系。当一个对象状态改变时所有依赖它的对象都会收到通知。ROS2的发布-订阅机制就是这个模式的实现。话题Topic是被观察的对象订阅者是观察者发布者负责通知。用C实现一个简单的观察者模式#include functional #include vector #include string // 观察者接口 templatetypename EventType class Observer { public: virtual void onEvent(const EventType event) 0; virtual ~Observer() default; }; // 被观察者主题 templatetypename EventType class Subject { std::vectorObserverEventType* observers_; public: void subscribe(ObserverEventType* observer) { observers_.push_back(observer); } void unsubscribe(ObserverEventType* observer) { observers_.erase( std::remove(observers_.begin(), observers_.end(), observer), observers_.end()); } void notify(const EventType event) { for (auto* observer : observers_) { observer-onEvent(event); } } };在机器人系统里激光雷达数据发布后可能有多个模块需要接收导航模块要用来避障建图模块要用来更新地图显示模块要用来可视化。这就是典型的观察者模式。策略模式让行为可以动态切换策略模式的定义定义一系列算法把它们一个个封装起来并且使它们可以互相替换。在机器人开发里最常见的场景是导航策略的切换。比如机器人在不同环境下用不同的导航策略开阔地带用直线导航狭窄通道用慢速精确导航人多的地方用保守导航。// 策略接口 class NavigationStrategy { public: virtual void navigate(const Pose current, const Pose target) 0; virtual ~NavigationStrategy() default; }; // 具体策略 class FastNavigation : public NavigationStrategy { public: void navigate(const Pose current, const Pose target) override { // 直线路径规划速度优先 cout Fast navigation to target endl; } }; class CautiousNavigation : public NavigationStrategy { public: void navigate(const Pose current, const Pose target) override { // 保守路径规划安全优先 cout Cautious navigation to target endl; } }; // 上下文机器人控制器 class RobotController { unique_ptrNavigationStrategy strategy_; public: void setStrategy(unique_ptrNavigationStrategy strategy) { strategy_ std::move(strategy); } void update(const Pose current, const Pose target) { strategy_-navigate(current, target); } };使用的时候RobotController controller; // 开阔地带用快速导航 controller.setStrategy(make_uniqueFastNavigation()); controller.update(current_pose, target_pose); // 进入狭窄区域切换到保守导航 controller.setStrategy(make_uniqueCautiousNavigation()); controller.update(current_pose, target_pose);策略模式的好处是把算法的定义和使用分开。新增一种导航策略不需要改RobotController的代码。观察者模式在ROS2中的实际应用ROS2的回调函数本质上就是观察者模式。你创建一个订阅者注册一个回调函数当消息到达时回调函数被调用。class LidarProcessor : public rclcpp::Node { public: LidarProcessor() : Node(lidar_processor) { subscription_ this-create_subscriptionsensor_msgs::msg::LaserScan( scan, 10, [this](const sensor_msgs::msg::LaserScan::SharedPtr msg) { processScan(msg); }); } private: void processScan(const sensor_msgs::msg::LaserScan::SharedPtr msg) { // 处理激光雷达数据 } rclcpp::Subscriptionsensor_msgs::msg::LaserScan::SharedPtr subscription_; };这里的Lambda表达式就是观察者。它观察scan这个话题当有新消息时被通知执行。ROS2的回调组Callback Group也是观察者模式的延伸。你可以把多个回调放在同一个组里控制它们的执行顺序和并发方式。面试中的考点观察者模式和发布-订阅模式有什么区别严格来说发布-订阅是观察者模式的变体。经典观察者模式里观察者和被观察者是紧耦合的发布-订阅模式通过中间的消息代理解耦了两者。ROS2用的是发布-订阅模式。策略模式和状态模式有什么区别策略模式是让用户选择算法状态模式是让系统根据当前状态自动切换行为。策略模式的切换是主动的状态模式的切换是被动的。这个区别面试经常考。观察者模式有什么性能问题如果观察者很多通知的开销会很大。而且观察者的执行顺序不确定如果观察者之间有依赖关系可能出问题。在机器人系统里通常用优先级队列来控制通知顺序。给正在准备面试的你观察者模式和策略模式在机器人开发里用得非常多。面试的时候能把设计模式和实际项目结合起来讲比单纯背定义强得多。比如你可以说我们的导航系统用策略模式实现了多种导航算法的切换用观察者模式实现了传感器数据的分发。这比我知道观察者模式是什么有说服力得多。下篇聊状态模式——机器人行为管理的优雅方案。在聊状态模式之前再提醒一点观察者模式在多线程环境下的线程安全问题经常被忽略。如果主题和观察者在不同线程通知时必须加锁或者用线程安全的消息队列否则很容易出竞态条件导致的bug。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第46篇 设计模式之单例与工厂——机器人传感器管理中的实际应用 下一篇预告第48篇 设计模式之状态模式——机器人行为管理的优雅方案有任何问题欢迎评论区留言我会尽量回复。