📋 摘要
  • C++ 设计模式面试高频问答,每题保留回答重点与扩展知识
  • 详细原理解析与代码示例见 03-Resources/cpp/C++ 设计模式
  • 持续补充中

1. 六大设计原则(SOLID)是什么?

📋 回答重点
  • SOLID 是五个面向对象设计原则:单一职责 SRP、开闭 OCP、里氏替换 LSP、接口隔离 ISP、依赖倒置 DIP,中文语境再加迪米特法则共「六大原则」。
  • SRP:一个类只负责一件事,只有一个引起它变化的原因。
  • OCP:对扩展开放、对修改关闭——加功能不改旧代码。
  • LSP:子类必须能完全替换父类,不破坏程序正确性。
  • ISP:接口小而专,客户端不依赖它用不到的方法。
  • DIP:高层与低层都依赖抽象,不依赖具体实现;迪米特法则即「最少知识原则」。

扩展知识

  • OCP 是「目标」,SRP/LSP/ISP/DIP 是达成它的「手段」,回答时点出这个递进关系是加分项。
  • 详细讲解:03-Resources/cpp/C++ 设计模式

2. 单例模式(懒汉/饿汉/线程安全)如何实现?

📋 回答重点
  • 保证一个类全局只有一个实例:私有构造函数 + 删除拷贝 + 静态访问方法。
  • 懒汉:首次调用才创建;饿汉:main 之前即创建(无线程问题但可能浪费)。
  • C++11 起推荐 Meyers 单例——函数内静态局部变量,初始化天然线程安全。
  • 双检锁 DCLP 需 std::atomic 配合 acquire/release 内存序,现在生产优先用 Meyers。
  • 典型应用:配置管理器、日志器、连接池、线程池。

扩展知识

  • 易错:忘记 = delete 拷贝构造/赋值会导致可复制出第二实例;单例跨 DLL 析构顺序不可控。
  • 详细讲解:03-Resources/cpp/C++ 设计模式

3. 简单工厂、工厂方法、抽象工厂的区别?

📋 回答重点
  • 三者都是把「对象创建与使用」解耦,区别在抽象层级与扩展方式。
  • 简单工厂:一个工厂类 + 一个方法,按参数返回不同产品;加新产品要改工厂(违反 OCP)。
  • 工厂方法:每个产品对应一个工厂类,加新产品只需加类,不改旧代码。
  • 抽象工厂:创建一组相关/相互依赖的产品族(如 Windows 家族 vs Mac 家族)。
  • 一句话记:简单工厂=一个函数造所有;工厂方法=一个工厂造一种;抽象工厂=一个工厂造一族。

扩展知识


4. 建造者模式如何实现?

📋 回答重点
  • 将复杂对象的构造过程与表示分离,支持分步构建 + 链式调用(fluent interface)。
  • 结构:产品 + 抽象建造者 + 具体建造者 + 指挥者(Director 固定组装流程)。
  • 关键写法:.setA().setB().build() 链式返回 *this。
  • 与工厂区别:工厂一步到位造对象,建造者分步骤、参数可组合、有默认值。
  • 应用:配置对象、HTTP 请求、SQL 语句、ProtoBuf 消息构造。

扩展知识


5. 原型模式如何实现?

📋 回答重点
  • 通过克隆已有对象创建新对象,而非 new,核心是 clone() 方法。
  • 适用创建成本高(初始化耗时、依赖 DB/网络)的对象。
  • C++ 借助拷贝构造实现深拷贝;典型结构:原型接口 + 具体类 + 原型注册表按 key 克隆。
  • 与工厂区别:工厂是「新造」,原型是「复制模板」。

扩展知识


6. 适配器模式如何实现?

📋 回答重点
  • 把类的接口转换成客户端期望的另一个接口,让不兼容的类协同工作。
  • C++ 两种实现:类适配器(多继承)与对象适配器(组合),后者更常用。
  • 应用:对接第三方库/遗留代码、统一多个相似接口、格式转换。
  • 与装饰器/代理都「包一层」,区别在意图:适配器改接口、装饰器加功能、代理控访问。

扩展知识


7. 装饰器模式如何实现?

📋 回答重点
  • 不修改原类,动态给对象叠加职责,且可层层嵌套(如加糖加奶的咖啡)。
  • 结构:组件接口 + 具体组件 + 抽象装饰器(既是一个组件又持有一个组件)+ 具体装饰器。
  • 与继承对比:继承编译期静态扩展、易类爆炸;装饰器运行期动态组合。
  • C++ 输入/输出流(std::fstream/std::istringstream)本质是装饰器应用。

扩展知识


8. 代理模式如何实现?

📋 回答重点
  • 为对象提供替身/占位,控制对它的访问。
  • 变体:虚拟代理(延迟加载)、远程代理(RPC 存根)、保护代理(权限)、日志代理。
  • 典型例子:大图延迟加载——首次 display 才真正创建 RealImage。
  • 与装饰器/适配器区别在意图:代理控制访问、装饰器增强功能、适配器改变接口。

扩展知识


9. 外观模式如何实现?

📋 回答重点
  • 为复杂子系统提供统一的高层接口,简化客户端调用。
  • 结构:一个 Facade 类封装多个子系统对象,暴露简单方法(如电脑 start/shutdown)。
  • 应用:复杂库/框架易用入口、分层架构隔离子系统、遗留系统封装。
  • 与中介者区别:外观是单向简化入口,中介者是双向协调子系统通信。

扩展知识


10. 桥接模式如何实现?

📋 回答重点
  • 将抽象部分与实现部分分离,两者可独立变化,核心是「组合代替继承」。
  • 结构:Abstraction(形状)持有 Implementor(颜色),避免 n×m 类爆炸。
  • 应用:两个独立变化维度(形状+颜色、设备+操作系统)、运行时切换实现。
  • 与策略模式结构极像,区别:桥接是结构性(分离抽象与实现),策略是行为性(切换算法)。

扩展知识


11. 组合模式如何实现?

📋 回答重点
  • 将对象组织成树形结构,统一处理单个对象与组合对象(文件与文件夹)。
  • 结构:统一 Component 接口 + Leaf(叶子)+ Composite(组合,含 children 集合)。
  • Composite 的 operation 递归调用子节点。
  • 应用:文件系统、UI 控件树、菜单树、AST 语法树。

扩展知识


12. 观察者模式如何实现?

📋 回答重点
  • 定义一对多依赖,被观察者(Subject)状态变化时自动通知所有观察者(Observer)。
  • 结构:Subject 维护观察者列表,提供 attach/detach/notify;Observer 实现 update。
  • 应用:事件驱动、GUI 事件、消息订阅、数据变化联动。
  • 常见坑:通知中删除观察者导致悬空指针、回调里再触发通知造成死循环。

扩展知识


13. 策略模式如何实现?

📋 回答重点
  • 定义一系列算法并封装成可互换对象,让算法独立于客户端变化。
  • 结构:策略接口 + 具体策略(QuickSort/MergeSort)+ 上下文(Sorter 持有策略)。
  • 运行时可 setStrategy 切换,消除大量 if-else。
  • 与状态模式结构像,区别:策略是客户端主动选算法,状态是对象自身状态驱动。

扩展知识


14. 模板方法模式如何实现?

📋 回答重点
  • 父类定义算法骨架,可变步骤延迟到子类实现,子类只填空不改流程。
  • 结构:父类非虚方法定流程 + protected 纯虚「钩子」方法由子类实现。
  • 体现「好莱坞原则」:Don’t call us, we’ll call you(框架调用你)。
  • 与策略区别:模板方法用继承(编译期定骨架),策略用组合(运行期换算法)。

扩展知识


15. 责任链模式如何实现?

📋 回答重点
  • 多个处理器串成链,请求沿链传递,直到某个处理器处理(或都不处理)。
  • 结构:Handler 持有 next 指针,自己不处理则调用 Handler::handle(request) 传给下一个。
  • 应用:审批流、日志分级、HTTP 中间件、异常处理链。
  • 两种变体:拦截式(每个都过,如中间件)与终止式(首个能处理的处理并停止,如审批)。

扩展知识


16. 状态模式如何实现?

📋 回答重点
  • 对象内部状态改变时改变行为,把每个状态封装成独立类。
  • 结构:State 接口 + 具体状态 + Context 持有当前状态,request 委托给状态处理。
  • 应用:订单状态机、TCP 连接状态、工作流引擎。
  • 核心收益:消除大量 if-else/switch 条件分支。

扩展知识


17. 命令模式如何实现?

📋 回答重点
  • 把请求封装成对象,支持参数化、排队、日志、撤销/重做。
  • 结构:Command 接口(execute + undo)+ 具体命令 + 接收者 + 调用者(Invoker 维护历史栈)。
  • 应用:编辑器撤销/重做、任务队列、GUI 按钮、事务回滚。
  • 本质是「回调/函数对象的面向对象化」。

扩展知识


18. 迭代器模式如何实现?

📋 回答重点
  • 顺序访问聚合对象元素而不暴露内部表示。
  • 核心:begin()/end() + operator++ + operator*(实现指针语义)。
  • C++ STL 已内置迭代器,配合泛型算法实现容器与算法彻底解耦。
  • 应用:自定义容器、遍历树/图等复杂结构、统一遍历接口。

扩展知识


19. 享元模式如何实现?

📋 回答重点
  • 共享不可变的内在状态,大量减少内存占用。
  • 内在状态可共享、不变(如字体名称+字号);外在状态随场景变化(如位置 x,y)由客户端传入。
  • 结构:享元对象 + 享元工厂(按内在状态 key 缓存复用)。
  • 应用:文字排版、游戏粒子、缓存池。

扩展知识


20. 中介者、备忘录、访问者模式各解决什么问题?

📋 回答重点
  • 中介者:解决多对象网状通信的耦合爆炸,所有交互都走中间人,变成星形结构(聊天室、MVC Controller、机场塔台)。
  • 备忘录:解决对象状态快照与恢复(撤销),在不破坏封装前提下保存/恢复状态。
  • 访问者:在不修改元素类的前提下为对象结构添加新操作,用双重分派实现。
  • 备忘录 vs 命令实现撤销:备忘录存快照(省逻辑占内存),命令重放逆操作(省内存需可逆)。

扩展知识

  • 访问者适合「元素稳定、操作多变」(如编译器 AST);新增元素会违反开闭原则,需改所有 Visitor。
  • 详细讲解:03-Resources/cpp/C++ 设计模式