《C++ Software Design》第三章 The Purpose of Design Patterns
Design patterns serve as standardized solutions to recurring problems in software design. They provide a common vocabulary for developers and establish best practices that have been proven effective through years of practical experience.
Key purposes include:
- Problem-Solving: They offer ready-made solutions to common design challenges (e.g., the Observer pattern for event handling systems or the Singleton pattern for resource management)
- Communication Enhancement: Patterns create a shared language that simplifies team discussions (e.g., saying "we'll use a Factory here" conveys complex implementation concepts concisely)
- Code Quality Improvement: By following established patterns, developers can avoid common pitfalls and produce more maintainable code
- Architectural Consistency: Patterns help maintain uniform design approaches across large projects
- Knowledge Transfer: They encapsulate decades of collective programming wisdom into reusable concepts
Common application scenarios:
- Enterprise systems (using patterns like MVC for web applications)
- Game development (employing patterns like State for character behavior)
- Operating systems (utilizing patterns like Proxy for resource access control)
Example: The Strategy pattern allows switching between different algorithms at runtime, useful in payment processing systems where payment methods (credit card, PayPal, etc.) can be dynamically selected without changing client code.
Guideline 11: Understand the Purpose of Design Patterns
设计模式不仅仅是一段可复用的代码片段,更是一种沉淀了大量实践经验的沟通与设计手段。具体而言,它具备以下四个要素:
11.1 A Design Pattern Has a Name
-
含义:模式名称是团队成员快速达成共识的"代号"。
-
示例:提及"策略模式(Strategy)"时,即意味着"可变行为在运行时可被封装到策略对象中,并由客户端按需选择"。
-
实践建议:
- 在文档、UML 图、PR 描述中始终使用标准英文名称;
- 若团队自造名称,务必在知识库中给出对应规范名称的映射,避免歧义。
11.2 A Design Pattern Carries an Intent
-
含义:每个模式都有一个简洁且明确的"意图(Intent)",回答"为什么要这么做"。
-
示例:
- Observer:当一个对象状态变化时,需要自动通知所有依赖者并同步更新。
- Factory Method:将对象创建逻辑从使用者中分离,使用者仅依赖抽象接口。
-
实践要点:
- 在设计评审前,先将模式意图写成一句话;
- 对照意图检查实现代码是否真正解决了该问题。
11.3 A Design Pattern Introduces an Abstraction
-
含义:模式通过抽象接口(基类或概念)把"可变部分"和"固定部分"分离。
-
示例(装饰者模式 Decorator):
cppstruct Component { virtual void operation() = 0; }; class ConcreteComponent : public Component { void operation() override { /* 原始逻辑 */ } }; class Decorator : public Component { std::unique_ptr<Component> wrappee_; public: Decorator(std::unique_ptr<Component> c) : wrappee_(std::move(c)) {} void operation() override { // 额外行为(前) wrappee_->operation(); // 额外行为(后) } };
- 抽象接口
Component
定义了通用契约,装饰者Decorator
只需依赖该接口即可插入额外职责。
- 抽象接口
11.4 A Design Pattern Has Been Proven
-
含义:模式来源于大量项目积累,已在社区和企业级系统中得到验证。
-
案例证据:
- 大型金融系统中,使用工厂模式和依赖注入框架后,新增交易类型时的改动量平均减少 40%。
- 某开源数据库通过策略模式替换存储引擎后,实现了无需重启的热切换功能。
-
警示:不要盲目搬用------理解模式的适用场景和权衡,才能发挥其真正价值。
Guideline 12: Beware of Design Pattern Misconceptions
不要把"使用模式"当成项目目标,也不要陷入对实现细节或偏见的误区。
12.1 Design Patterns Are Not a Goal
- 误区:为了"炫技"或"达标"而硬塞模式。
- 真相:模式是解决特定问题的工具,若业务场景简单,直接函数或小型类划分即可,无需复杂模式。
12.2 Design Patterns Are Not About Implementation Details
- 误区:关注 UML 静态类图,复制示例代码到项目中。
- 真相:先要洞察设计意图,再结合 C++ 特性(继承、模板、lambda、constexpr)灵活实现。
12.3 Design Patterns Are Not Limited to OOP or Dynamic Polymorphism
-
误区:以为所有模式都要靠虚函数和继承。
-
真相:
-
编译时策略模式:
cpptemplate<typename Strategy> class Context { Strategy strat_; public: auto execute(auto&&... args) { return strat_.doAlgorithm(std::forward<decltype(args)>(args)...); } };
-
静态多态(CRTP 实现):如静态 Visitor 模式。
-
Guideline 13: Design Patterns Are Everywhere
良好的设计早已渗透于标准库和第三方库之中。学会识别并借鉴它们的实现,能快速提升自身设计能力。
-
Iterator 模式:
std::vector<T>::iterator
、std::begin
/std::end
即是典型迭代器。
-
Adapter 模式:
std::istream_iterator
将流接口适配为迭代器。
-
Singleton 模式(谨慎使用):
- 常见于日志、配置中心,但要留意线程安全和可测试性。
建议:在阅读 STL 源码或公司框架时,列出遇到的模式名称,并写成短文档,供团队分享。
Guideline 14: Use a Design Pattern's Name to Communicate Intent
-
代码注释与文档
cpp// 使用桥接模式(Bridge)实现图形设备和渲染后端分离 class Renderer; class shape { Renderer& renderer_; public: shape(Renderer& r): renderer_(r) {} virtual void draw() = 0; };
-
PR 描述
"本 PR 引入责任链模式(Chain of Responsibility),用于动态构造请求处理流水线"
-
效果
- 评审者一看模式名,即可快速了解设计意图;
- 降低沟通成本,加强团队对设计架构的共识。