3.《设计模式》:软件设计与解耦能力提炼

第三阶段学习目标:理解常见的软件设计问题,以及如何使用抽象、组合、接口和多态控制复杂度。

核心思想:

不要背设计模式,要理解"为什么需要这种设计"。


目录

  • [1. 设计模式到底解决什么?](#1. 设计模式到底解决什么?)
  • [2. 第一原则:组合优于继承](#2. 第一原则:组合优于继承)
  • [3. Strategy:策略模式](#3. Strategy:策略模式)
  • [4. Factory:工厂模式](#4. Factory:工厂模式)
  • [5. Adapter:适配器模式](#5. Adapter:适配器模式)
  • [6. Facade:外观模式](#6. Facade:外观模式)
  • [7. Observer:观察者 / 事件模式](#7. Observer:观察者 / 事件模式)
  • [8. Command:命令模式](#8. Command:命令模式)
  • [9. State:状态模式](#9. State:状态模式)
  • [10. Dependency Injection:依赖注入](#10. Dependency Injection:依赖注入)
  • [11. 设计模式真正应该学习什么?](#11. 设计模式真正应该学习什么?)
  • [12. 设计模式的反模式](#12. 设计模式的反模式)
  • [13. AI Coding 中如何使用设计模式?](#13. AI Coding 中如何使用设计模式?)
  • [14. 本阶段最终能力](#14. 本阶段最终能力)

1. 设计模式到底解决什么?

设计模式不是为了让代码显得高级。

它解决的是反复出现的软件设计问题:

text 复制代码
需求变化
 ↓
代码结构开始复杂
 ↓
找到变化点
 ↓
隔离变化
 ↓
减少影响范围

所以设计模式与前面的"高内聚、低耦合、封装变化"是一脉相承的。


2. 第一原则:组合优于继承

不要看到不同类型就马上建立复杂继承树。

很多时候:

text 复制代码
继承

容易形成强耦合。

而:

text 复制代码
组合

更灵活。

例如:

text 复制代码
ModelService
 ├── Loader
 ├── Cache
 ├── CoordinateTransformer
 └── Logger

ModelService 通过组合获得能力。


3. Strategy:策略模式

适合:

同一个业务流程存在多个可替换算法 / 实现。

例如 GIS 模型加载:

text 复制代码
ModelLoader
 ├── OSGBLoader
 ├── Tiles3DLoader
 ├── GLTFLoader
 └── OBJLoader

上层只依赖:

text 复制代码
ModelLoader

4. Factory:工厂模式

适合:

创建对象的逻辑比较复杂,或者创建过程需要根据类型选择实现。

例如:

text 复制代码
createModelLoader(type)

根据:

text 复制代码
"osgb"
"3dtiles"
"gltf"

返回不同 Loader。

注意:

简单对象不要为了"设计模式"强行使用 Factory。


5. Adapter:适配器模式

适合:

两个接口不兼容,但你希望它们能够协作。

例如:

text 复制代码
你的业务接口
     ↓
ModelLoader
     ↓
第三方 GIS SDK

如果第三方 SDK 的接口与你的业务接口不同,可以通过 Adapter 转换。


6. Facade:外观模式

适合:

一个复杂系统对外只需要暴露一个简单入口。

例如:

text 复制代码
GISFacade

内部:

text 复制代码
SceneManager
ModelManager
TerrainManager
CameraManager
CoordinateService

外部只需要:

text 复制代码
gis.loadProject()

7. Observer:观察者 / 事件模式

适合:

一个事件发生后,多个模块需要响应,但不希望它们互相直接依赖。

例如:

text 复制代码
ModelService
    ↓
model:loaded
    ↓
 ┌──────────┬──────────┐
 ↓          ↓          ↓
UI       Logger    SceneManager

非常适合:

  • Electron
  • 前端
  • 状态变化
  • GIS 场景事件
  • 异步任务

8. Command:命令模式

把:

"一个操作"

封装成对象或独立命令。

例如:

text 复制代码
LoadModelCommand
RemoveModelCommand
MoveModelCommand

适合进一步实现:

  • Undo
  • Redo
  • 操作记录
  • 批量执行
  • 命令队列

GIS 编辑类软件尤其值得理解。


9. State:状态模式

当一个对象的行为会随着状态变化而变化时,可以显式建模状态。

例如:

text 复制代码
Model
 ├── Idle
 ├── Loading
 ├── Loaded
 ├── Failed
 └── Disposed

这比到处使用:

text 复制代码
isLoading
isLoaded
isError

更容易控制复杂度。


10. Dependency Injection:依赖注入

核心思想:

不要让一个模块自己决定所有依赖。

例如不推荐:

text 复制代码
ModelService
 ↓
new CesiumModelLoader()

可以考虑:

text 复制代码
ModelService
 ↓
ModelLoader

然后外部注入:

text 复制代码
ModelService(loader)

这样测试时可以传:

text 复制代码
FakeModelLoader

从而降低耦合、提高可测试性。


11. 设计模式真正应该学习什么?

不要记:

text 复制代码
Strategy = 策略
Factory = 工厂
Observer = 观察者

而要记:

text 复制代码
什么问题?
 ↓
什么变化?
 ↓
哪里耦合?
 ↓
如何隔离?

例如:

为什么使用 Strategy?

不是因为:

"Strategy 是经典设计模式。"

而是因为:

这里有多个可替换算法,而且未来可能继续增加。


12. 设计模式的反模式

常见错误:

text 复制代码
简单问题
 ↓
硬套设计模式
 ↓
Factory + AbstractFactory + Strategy + Adapter
 ↓
代码复杂度暴涨

最终:

设计模式解决的问题比原来的问题还复杂。

所以应该遵循:

先有问题,再有模式。


13. AI Coding 中如何使用设计模式?

不要问:

text 复制代码
"这里帮我用设计模式优化。"

更好的问法:

text 复制代码
当前代码存在多个模型格式。

请分析:
1. 这些实现有哪些变化点?
2. 是否存在高耦合?
3. Strategy / Factory / Adapter 哪种更适合?
4. 是否真的有必要引入设计模式?
5. 最简单的方案是什么?

这会训练你的设计判断能力。


14. 本阶段最终能力

能够看到一个问题时自然思考:

text 复制代码
这里什么会变化?
       ↓
能不能封装?
       ↓
能不能通过接口隔离?
       ↓
能不能通过组合降低耦合?
       ↓
有没有必要使用某种设计模式?

最终目标:

不是会背设计模式,而是会识别设计问题。

相关推荐
染指11101 小时前
131.Agent-Agent设计模式-MAS多智能体系统(Multi-Agent-System)
人工智能·设计模式·langchain·agent·agents
ShyanZh16 小时前
【Python3基础】13-Python 常用设计模式
开发语言·python·设计模式
YYYing.1 天前
【设计模式系列 (五) 】原型模式
开发语言·后端·设计模式·原型模式·c/c++
长按助力退休2 天前
设计模式实战,这 5 个最常用
设计模式
Carl_奕然2 天前
【智能体】Agent的四种设计模式之:Multi-Agent Collaboration
设计模式
Lost of 程序猿2 天前
建造者模式实战:告别“十参数构造函数“的数据导出任务
后端·设计模式·c#·asp.net
SL_staff2 天前
合规性折旧:当知识资产因主权缺位在审计中‘功能性清零’
java·设计模式·开源
Zane19942 天前
工厂方法一定比简单工厂高级?三种工厂模式到底该怎么选
设计模式
Hespethorn2 天前
设计模式是语言缺陷的补丁 —— 从工厂、单例、策略三个模式说起
设计模式