设计模式的本质
设计模式的本质是在「变化」与「稳定」之间划界让系统对扩展开放、对修改关闭。几乎所有模式都在回答同一个问题哪一部分将来最可能变怎样让「变」不影响「不变」建议的学习顺序设计原则几种高频模式读框架源码自己项目小步重构易混模式对照高频模式建议优先观察者、策略、工厂、组合、命令、装饰。它们覆盖了日常 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模式几乎总是重构的目标形状而不是项目启动时的第一张架构图满屏 if-else → 策略 / 状态 类越来越大 → 单一职责 / 门面 继承树爆炸 → 桥接 / 组合 / 装饰 对象互相引用成网 → 中介者 / 观察者 创建逻辑散落各处 → 工厂 / 原型 撤销重做难做 → 命令 备忘录会嗅坏味道比会背 23 个名字更接近本质。4. 模式是「角色关系」不是固定类名GoF 描述的是角色Context、Strategy、ConcreteStrategySubject、Observer……真实代码里可以叫Checkout、PaymentStrategy、Alipay——角色不变命名随意。同一系统里常多个模式叠加命令 备忘录 → 撤销栈组合 迭代器 → 遍历文档树工厂 单件 → 全局配置管理策略 模板方法 → 框架定流程、应用填步骤模式的本质是可复用的微型架构片段。5. 三类模式管三件不同的事类型本质问题一句话创建型对象怎么来把new从业务里挪走隐藏构造复杂度结构型类怎么拼用组合、包装、适配组织更大结构行为型职责怎么分、怎么通信算法、状态、通知、请求如何流动创建型管诞生结构型管形状行为型管动作与协作——这是对复杂度的三种切分。6. 模式有代价用复杂换灵活每种模式都带来更多的类与接口更多的间接层更高的理解成本因此模式的另一面是有意识地接受一定复杂度换取未来的可扩展性。简单问题用简单解法模式不是勋章是在确认真有变化压力时的投资。7. 模式 vs 框架 vs 语言设计模式框架Qt / VTK现代 C是什么设计经验的名字已实现的大结构语言级抽象例子策略、观察者信号槽、vtkInteractorStylestd::function、RAII关系思想层模式已嵌入 API可简化实现思想仍在STL 迭代器 迭代器模式的标准化std::function 轻量策略 / 命令Qt 信号槽 观察者思想的框架化vtkCommand Observer 回调载体名字像 Command语义不是 GoF 命令见 VTK 专题本质在思想形态随语言与框架演进。重点与注意速记重点模式 变化点隔离 依赖抽象 组合复用的命名结构。重点从坏味道出发重构比一上来「模式驱动设计」更务实。注意模式是角色关系可叠加不是每个类只能戴一顶帽子。注意框架里已内置大量模式读 API 也是在读模式落地。