设计模式的本质

设计模式的本质,是在「变化」与「稳定」之间划界,让系统对扩展开放、对修改关闭。

几乎所有模式都在回答同一个问题:哪一部分将来最可能变?怎样让「变」不影响「不变」?

建议的学习顺序

#mermaid-svg-zM7CTIIAlhZlHRxo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zM7CTIIAlhZlHRxo .error-icon{fill:#552222;}#mermaid-svg-zM7CTIIAlhZlHRxo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zM7CTIIAlhZlHRxo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zM7CTIIAlhZlHRxo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zM7CTIIAlhZlHRxo .marker.cross{stroke:#333333;}#mermaid-svg-zM7CTIIAlhZlHRxo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zM7CTIIAlhZlHRxo p{margin:0;}#mermaid-svg-zM7CTIIAlhZlHRxo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster-label text{fill:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster-label span{color:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster-label span p{background-color:transparent;}#mermaid-svg-zM7CTIIAlhZlHRxo .label text,#mermaid-svg-zM7CTIIAlhZlHRxo span{fill:#333;color:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo .node rect,#mermaid-svg-zM7CTIIAlhZlHRxo .node circle,#mermaid-svg-zM7CTIIAlhZlHRxo .node ellipse,#mermaid-svg-zM7CTIIAlhZlHRxo .node polygon,#mermaid-svg-zM7CTIIAlhZlHRxo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zM7CTIIAlhZlHRxo .rough-node .label text,#mermaid-svg-zM7CTIIAlhZlHRxo .node .label text,#mermaid-svg-zM7CTIIAlhZlHRxo .image-shape .label,#mermaid-svg-zM7CTIIAlhZlHRxo .icon-shape .label{text-anchor:middle;}#mermaid-svg-zM7CTIIAlhZlHRxo .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zM7CTIIAlhZlHRxo .rough-node .label,#mermaid-svg-zM7CTIIAlhZlHRxo .node .label,#mermaid-svg-zM7CTIIAlhZlHRxo .image-shape .label,#mermaid-svg-zM7CTIIAlhZlHRxo .icon-shape .label{text-align:center;}#mermaid-svg-zM7CTIIAlhZlHRxo .node.clickable{cursor:pointer;}#mermaid-svg-zM7CTIIAlhZlHRxo .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zM7CTIIAlhZlHRxo .arrowheadPath{fill:#333333;}#mermaid-svg-zM7CTIIAlhZlHRxo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zM7CTIIAlhZlHRxo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zM7CTIIAlhZlHRxo .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zM7CTIIAlhZlHRxo .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zM7CTIIAlhZlHRxo .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zM7CTIIAlhZlHRxo .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster text{fill:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo .cluster span{color:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zM7CTIIAlhZlHRxo .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zM7CTIIAlhZlHRxo rect.text{fill:none;stroke-width:0;}#mermaid-svg-zM7CTIIAlhZlHRxo .icon-shape,#mermaid-svg-zM7CTIIAlhZlHRxo .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zM7CTIIAlhZlHRxo .icon-shape p,#mermaid-svg-zM7CTIIAlhZlHRxo .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zM7CTIIAlhZlHRxo .icon-shape .label rect,#mermaid-svg-zM7CTIIAlhZlHRxo .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zM7CTIIAlhZlHRxo .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zM7CTIIAlhZlHRxo .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zM7CTIIAlhZlHRxo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 设计原则
几种高频模式
读框架源码
自己项目小步重构
易混模式对照

高频模式建议优先:观察者、策略、工厂、组合、命令、装饰

它们覆盖了日常 80% 的「变化点」问题。其余模式在碰到具体问题时再查,完全来得及。


1. 模式不是语法,是「变化点管理术」

设计模式既不是库,也不是框架,更不是某种 C++ 语法糖。它是在反复出现的场景里,类与对象如何分工协作的命名经验。

模式 隔离的变化点
策略 可互换的算法
观察者 谁会响应状态变化
工厂 具体类型如何被创建
桥接 抽象与实现两个维度
装饰 动态叠加的职责
命令 请求的发起与执行

读模式时,先问「这里的变化点是什么」,比背 UML 更有用。


2. 三条底层逻辑

GoF 23 种模式背后,反复出现三条主线:

2.1 依赖抽象,不依赖具体

高层模块不应绑死在 new FileLogger() 上,而应依赖 Logger 接口。换实现时,调用方不动------依赖倒置(DIP),策略、工厂、桥接的共同地基。

2.2 组合优于继承

继承是白盒复用,子类与父类紧耦合。Has-A(持有一个策略、包一层装饰)是黑盒复用,往往更灵活。策略、装饰、桥接都在践行合成复用(CRP)

2.3 分离「做什么」与「谁来做 / 何时做」

分离什么 典型模式
算法 vs 使用算法的上下文 策略
请求 vs 执行者 命令
通知 vs 响应 观察者
构造 vs 使用 工厂、建造者
树形结构 vs 遍历方式 组合 + 迭代器

本质都是降低耦合、让职责更单一(SRP)。

先原则,再模式


3. 模式从「坏味道」反推,不是从空白纸画 UML

模式几乎总是重构的目标形状,而不是项目启动时的第一张架构图:

text 复制代码
满屏 if-else           → 策略 / 状态
类越来越大             → 单一职责 / 门面
继承树爆炸             → 桥接 / 组合 / 装饰
对象互相引用成网       → 中介者 / 观察者
创建逻辑散落各处       → 工厂 / 原型
撤销重做难做           → 命令 + 备忘录

会嗅坏味道,比会背 23 个名字更接近本质。


4. 模式是「角色关系」,不是固定类名

GoF 描述的是角色:Context、Strategy、ConcreteStrategy;Subject、Observer......

真实代码里可以叫 CheckoutPaymentStrategyAlipay------角色不变,命名随意

同一系统里常多个模式叠加:

  • 命令 + 备忘录 → 撤销栈
  • 组合 + 迭代器 → 遍历文档树
  • 工厂 + 单件 → 全局配置管理
  • 策略 + 模板方法 → 框架定流程、应用填步骤

模式的本质是可复用的微型架构片段


5. 三类模式:管三件不同的事

类型 本质问题 一句话
创建型 对象怎么来 new 从业务里挪走,隐藏构造复杂度
结构型 类怎么拼 用组合、包装、适配组织更大结构
行为型 职责怎么分、怎么通信 算法、状态、通知、请求如何流动

创建型管诞生 ,结构型管形状 ,行为型管动作与协作------这是对复杂度的三种切分。


6. 模式有代价:用复杂换灵活

每种模式都带来:

  • 更多的类与接口
  • 更多的间接层
  • 更高的理解成本

因此模式的另一面是:有意识地接受一定复杂度,换取未来的可扩展性

简单问题用简单解法;模式不是勋章,是在确认真有变化压力时的投资


7. 模式 vs 框架 vs 语言

设计模式 框架(Qt / VTK) 现代 C++
是什么 设计经验的名字 已实现的大结构 语言级抽象
例子 策略、观察者 信号槽、vtkInteractorStyle std::function、RAII
关系 思想层 模式已嵌入 API 可简化实现,思想仍在
  • STL 迭代器 = 迭代器模式的标准化
  • std::function = 轻量策略 / 命令
  • Qt 信号槽 = 观察者思想的框架化
  • vtkCommand = Observer 回调载体(名字像 Command,语义不是 GoF 命令,见 VTK 专题

本质在思想;形态随语言与框架演进。


重点与注意(速记)

重点 :模式 = 变化点隔离 + 依赖抽象 + 组合复用 的命名结构。

重点 :从坏味道出发重构,比一上来「模式驱动设计」更务实。

注意 :模式是角色关系,可叠加;不是每个类只能戴一顶帽子。

注意:框架里已内置大量模式;读 API 也是在读模式落地。

相关推荐
晚安code2 小时前
干掉成山的 if-else:工厂造、策略选,一文讲透两个模式的配合
后端·设计模式
workflower10 小时前
从幻觉,到现实
人工智能·深度学习·机器学习·设计模式·机器人
电子科技圈11 小时前
第二代无线平台历久弥新,赋能物联网创新迭代
人工智能·嵌入式硬件·mcu·物联网·设计模式·硬件架构·iot
choumin21 小时前
创建型模式——工厂方法模式
c++·设计模式·工厂方法模式·创建型模式
choumin1 天前
创建型模式——原型模式
c++·设计模式·原型模式·创建型模式
37.2℃9951 天前
Claude Design哪个公司技术好
python·设计模式
阿懂在掘金1 天前
Vue 弹窗新范式——代码减少、复用翻倍与 AI 时代的前端基建
前端·设计模式·前端框架
choumin1 天前
结构型模式——装饰模式
c++·设计模式·装饰模式·结构型模式
choumin1 天前
结构型模式——组合模式
c++·设计模式·组合模式·结构型模式
workflower1 天前
供应链分销网络选址问题
人工智能·机器学习·设计模式·自然语言处理·机器人