从这篇开始进入设计模式专题。C面试里设计模式考得不少尤其是做机器人开发的——面试官想看你能不能把代码组织好。先聊两个最基础的单例模式和工厂模式。面试的时候面试官说设计一个传感器管理系统管理不同类型的传感器。我上来就写了个单例。面试官说为什么用单例我说因为传感器管理器全局只需要一个。面试官追问单例有什么缺点我当时答得不好。今天把这两个模式掰开了讲。单例模式全局唯一实例单例模式保证一个类只有一个实例并提供全局访问点。class SensorManager { static SensorManager* instance_; SensorManager() {} // 私有构造 public: static SensorManager* getInstance() { if (!instance_) { instance_ new SensorManager(); } return instance_; } // 删除拷贝构造和赋值 SensorManager(const SensorManager) delete; SensorManager operator(const SensorManager) delete; }; SensorManager* SensorManager::instance_ nullptr; // 使用 auto* mgr SensorManager::getInstance();这个经典写法有个问题线程不安全。两个线程同时调用getInstance()可能创建两个实例。线程安全的版本用Meyers单例C11后推荐class SensorManager { public: static SensorManager getInstance() { static SensorManager instance; // 局部静态变量线程安全 return instance; } private: SensorManager() {} }; // 使用 auto mgr SensorManager::getInstance();C11保证局部静态变量的初始化是线程安全的。这是最简单也最推荐的单例实现。但单例有个很大的问题它本质上是全局变量。全局变量的问题它都有——难以测试、隐藏依赖关系、生命周期不可控。面试官追问单例有什么缺点的时候正确答案是单例让代码之间的依赖关系变得不透明。你调用SensorManager::getInstance()看函数签名完全不知道它依赖了SensorManager。而且单例的生命周期跟程序一样长析构顺序在程序退出时很难控制。现代C的趋势是少用单例多用依赖注入——把对象通过参数传进去而不是让它自己去取全局实例。工厂模式创建对象的正确姿势工厂模式解决的是怎么创建对象的问题。最简单的形式是简单工厂class SensorBase { public: virtual void read() 0; virtual ~SensorBase() default; }; class LidarSensor : public SensorBase { public: void read() override { cout Reading lidar endl; } }; class IMUSensor : public SensorBase { public: void read() override { cout Reading IMU endl; } }; class CameraSensor : public SensorBase { public: void read() override { cout Reading camera endl; } }; // 简单工厂 class SensorFactory { public: static unique_ptrSensorBase create(const string type) { if (type lidar) return make_uniqueLidarSensor(); if (type imu) return make_uniqueIMUSensor(); if (type camera) return make_uniqueCameraSensor(); return nullptr; } }; // 使用 auto sensor SensorFactory::create(lidar); sensor-read();简单工厂的问题是每加一种传感器都要改工厂的create方法。违反了开闭原则。改进的方式是用注册机制——每种传感器自己注册创建函数工厂只需要查表就行。新增传感器类型不需要改工厂代码。// 注册机制用map存储创建函数 mapstring, functionunique_ptrSensorBase() registry; registry[lidar] []() { return make_uniqueLidarSensor(); }; registry[imu] []() { return make_uniqueIMUSensor(); }; // 新增类型只需注册 registry[camera] []() { return make_uniqueCameraSensor(); }; auto sensor registry[camera]();在机器人开发里工厂模式用得非常多。ROS2里的组件加载机制本质上就是工厂模式——根据类型名创建对应的组件实例。单例工厂的配合使用实际项目里单例和工厂经常配合使用——一个全局的传感器工厂管理所有类型的创建。不过讲真如果不是特别复杂的系统我倾向于不用单例。直接把工厂对象作为参数传递代码更清晰也更好测试。面试中的考点单例怎么保证线程安全C11之后用Meyers单例局部静态变量编译器保证初始化线程安全。老式写法需要加mutex。工厂模式和new有什么区别new创建的是具体类型工厂创建的是抽象接口。工厂让你面向接口编程新增类型不需要改使用方的代码。什么时候用单例什么时候用依赖注入如果确实需要全局唯一的资源比如日志系统单例可以接受。但大部分情况下依赖注入更好——通过构造函数把依赖传进来代码的可测试性和可维护性都更高。再聊一个工厂模式的进阶用法自注册工厂。传统工厂模式的问题是每新增一个产品类型都要修改工厂类的if-else或者switch违反开闭原则。自注册工厂的做法是让每个产品类在加载时自动向工厂注册自己的创建函数。具体实现是用一个全局的map存储类型名到创建函数的映射每个产品类在静态初始化时把自己的创建函数注册进去。这样新增产品时只需要写一个新类工厂类完全不需要改动。在机器人开发里插件系统经常用这种模式——每个插件自动注册主程序通过名字动态加载。面试时如果你能讲出自注册工厂的实现思路面试官会认为你对设计模式的理解已经超越了教科书层面。给正在准备面试的你单例和工厂是设计模式里最基础的两个。面试里考的不只是你会不会写更是你知不知道什么时候该用、什么时候不该用。能讲清楚单例的缺点、工厂的扩展性优势、以及依赖注入的替代方案面试官会觉得你不只是在套模板而是真正理解了设计背后的权衡。这比会写代码本身更重要。补充一个面试技巧面试官问设计模式时不要只答单例和工厂。你可以主动提到在实际项目里我们还用了策略模式来处理不同的传感器数据处理算法用观察者模式来实现事件通知。这样面试官会觉得你的模式储备不止两个项目经验也更丰富。当然前提是你确实了解这些模式的原理和应用场景别给自己挖坑。另外提一点面试时聊设计模式最好结合具体代码来讲。比如我们的传感器管理模块用了工厂模式不同类型的传感器通过统一的接口创建新增传感器类型只需要加一个工厂方法不需要改调用方的代码。这种有细节的回答比泛泛而谈我知道单例模式有说服力得多。下篇聊观察者模式和策略模式——ROS2回调与行为切换中的实际应用。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第45篇 CRTP模式——静态多态的实现技巧 下一篇预告第47篇 设计模式之观察者与策略——ROS2回调与行为切换有任何问题欢迎评论区留言我会尽量回复。
类型萃取与SFINAE:面试官问“怎么让模板只对特定类型生效”,我懵了 上篇聊了完美转发,今天进入模板编程的另一个深水区——类型萃取和SFINAE。说实话,这两个知识点在面试里不算高频考点。但一旦面试官想区分"会用模板"和"理解模板"的人,就会抛出来。面试的时候,面试官问"…
python-133-KeyCloak学习之(七)基于Keycloak实现单点登录 文章目录 1 场景 1.1 kc_config.py(共享配置) 1.2 kc_app_a.py(应用A) 1.2.1 初始化 1.2.2 路由GET /(检查登录状态) 1.2.3 路由GET /callback(Keycloak跳回来了) 1.2.4 整体代码 1.3 kc_app_b.py(应用B) 2 对比手写版 2.1 免密登录的魔法 2.2 代码量 1 场景 最大的变化:没有s…
BGP综合实验(广域网互通,AS,OSPF,EBGP,IBGP,汇总,防环) 一、实验需求1,AS1存在两个环回,一个地址为192.168.1.0/24该地址不能在任何协议中宣告AS3中存在两个环回,一个地址为192.168.2.0/24该地址不能在任何协议中宣告,最终要求这两个环回可以互相通讯AS1的另一个环回为10.0.0.0/24&…
VC++ 2015运行库部署实战:游戏开发环境搭建与排错指南 1. 项目概述:为什么游戏开发绕不开VC运行库? 如果你是一个游戏开发者,或者你尝试在Windows上运行过一些单机游戏、独立游戏,大概率遇到过这样的弹窗:“无法启动此程序,因为计算机中丢失VCRUNTIME140.dll”或…
深度优化UE5.1编译速度:解锁多核CPU性能的UBT配置指南 1. 项目概述:从“傻等”到“榨干”的编译革命 如果你正在用虚幻引擎5.1(UE5.1)做项目,尤其是那种动辄几十万行C代码的大型项目,那你一定对“编译”这两个字又爱又恨。爱的是,每一次编译都意味着新功能的诞生…
基于Semi Design的AI自动生成表单与网页开发实践 在实际前端开发中,表单和网页的重复性工作占据了大量开发时间。随着AI技术的快速发展,现在我们可以通过UI组件库的AI能力实现表单和网页的自动生成,大幅提升开发效率。本文将基于Semi Design等现代UI组件库,详细介绍如何利用AI技术…
3个核心策略:用思源笔记打造知识流动的终极指南 3个核心策略:用思源笔记打造知识流动的终极指南 【免费下载链接】siyuan A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. 项目地址: https://gitcode.com/GitHub_Trending/si/siyu…
Windows系统完美使用苹果苹方字体的终极解决方案:6种字重+双格式支持 Windows系统完美使用苹果苹方字体的终极解决方案:6种字重双格式支持 【免费下载链接】PingFangSC PingFangSC字体包文件、苹果平方字体文件,包含ttf和woff2格式 项目地址: https://gitcode.com/gh_mirrors/pi/PingFangSC 还在为Windows系统无法显…
Wireshark数据包分析实战:从捕获到生成专业报告的全流程指南 1. 项目概述:从“看热闹”到“看门道”的进阶之路 如果你在网络运维、安全分析或者应用开发的圈子里待过,那你一定听说过Wireshark。它就像网络世界的“显微镜”,能把那些看不见摸不着的比特流,变成一行行可以解读的协议对话。很多…
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单 更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…
某智驾大牛创业 作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…
PlantUML 实战:5分钟将 UML 2.5 序列图转换为可执行代码草图 PlantUML 实战:5分钟将 UML 2.5 序列图转换为可执行代码草图 在软件开发过程中,清晰的系统设计往往比编码本身更为关键。传统拖拽式UML工具虽然直观,却常常成为效率杀手——频繁的鼠标操作打断设计思路,版本控制困难,…
【RT-DETR涨点改进】29 动态Batch推理:让RT-DETR在低延迟下吃满GPU算力 29 动态Batch推理:让RT-DETR在低延迟下吃满GPU算力 开篇故事 上个月帮一家安防厂商做项目优化,他们用RT-DETR做实时人流统计,部署在NVIDIA A10上。客户反馈说:“GPU利用率才30%,但延迟已经飙到40ms了,加人流量就丢帧。” 我远程一看,好家伙——生产环境里每个请求单独…
Postman 环境变量实战:3种动态设置方法与CI/CD集成避坑指南 Postman 环境变量高阶实战:动态管理与 CI/CD 深度集成在接口自动化测试领域,环境变量的灵活运用往往成为区分初级与高级测试工程师的关键能力。本文将深入探讨 Postman 环境变量的三种动态设置模式,并分享 Newman 在 CI/CD 流水线中的实战避坑…
[C++]内存管理:串顺序存储的内存回收 在串(字符串)的顺序存储中,内存回收的方式取决于字符串的存储方式以及所使用的编程语言和相关库。以下以 C 为例进行说明,因为 C 对内存管理有较为直接的控制。 1. 基于 char 数组的串顺序存储 如果使用普通的 char 数组来存储字…
移动端游戏功耗测试实战:电流、功率、亮度和场景对比 移动端游戏功耗测试:先控制变量,再比较优化是否真的省电 摘要:功耗测试最容易犯的错误,是拿两次不同温度、不同亮度、不同场景的平均功率直接比较。本文给出一套可复现的游戏功耗测试方法,覆盖引擎特性验证、版本回归和黑盒体验测试,并说明如何把功耗与帧率、温控、CPU/G…
足球口袋教练 HarmonyOS 离线应用实战(03/20):ArkUI 首页仪表盘搭建 本文是“足球口袋教练 HarmonyOS 离线应用实战”系列第 3 篇。示例项目是一个 HarmonyOS / ArkTS / ArkUI 编写的离线足球训练助手,围绕真实页面、真实截图和可复现操作展开。 本篇要解决的问题 训练 App 的首页不能只展示欢迎语,它要解决“我现在该点哪…