设计模式现在已经讲烂了,经典是经典,之前也过了一遍,但日常使用的并不多。
之所以再次过一遍设计模式,是因为在梳理自己以往的笔记时,发现它还真是有些用的,结合自己的编程经验,发现自己之前写的好些代码的确可以用设计模式来重构。
这里仅作为一种编码思路再次整理一下逻辑。眼过千遍不如手过一遍,再次过一下,增强记忆,之后在遇到能够使用设计模式解决的问题时,需要能有这个意识,通过设计模式来优化。
其实设计模式,有说好,也有说不好。不是万能钥匙,但是合适的场景下确实有用。
- 建议先写能跑的代码,不要一开始就想着要怎么样去用设计模式。
- 三振法则:当发现同一个功能变化或者相似代码出现了三次以上时,再考虑引入设计模式。
- 记得写文档,在使用设计模式的地方加注释,说明为什么要这样更改。
之前看到一个比喻很贴切:设计模式就像电动螺丝刀,当你一天要拧 100 颗螺丝时,它让你事半功倍;如果只是偶尔拧一次,翻箱倒柜找电池的时间比手拧还慢。
不是"有没有用",而是"合不合适"。
场景 | 作用 | 举例 |
---|---|---|
代码频繁变化 | 封装变化点,减少连锁修改 | 用策略模式替换 if-else 算法分支 |
多人协作/长期维护 | 统一语言,降低心智成本 | 看到 Observer 就明白是发布-订阅关系 |
框架或中间件开发 | 提供扩展点,让用户不修改源码即可定制 | Spring 的 BeanFactory(工厂/抽象工厂) |
性能敏感且对象多 | 共享元数据,降低内存 | 文本编辑器中的 Glyph 享元对象 |
症状 | 原因 | 例子 |
---|---|---|
只有两三个 if-else | 过度设计 | 硬把简单逻辑拆成策略类,类爆炸 |
一次性脚本/原型 | 生命周期短,模式反而拖慢迭代 | 临时数据抓取脚本 |
团队不熟悉模式 | 看不懂抽象,调试困难 | 滥用装饰器导致栈式调用链难追踪 |
需求极少变动 | 模式带来的扩展性永远用不上 | 内部工具,功能五年不变 |
设计模式(Design Pattern)是软件开发中常见的最佳实践解决方案,它们是对常见编程问题的标准化解决方案。设计模式不是代码,而是一种编程思想,是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。
最经典的当属 GoF(Gang of Four)在《设计模式:可复用面向对象软件的基础》一书中提出的 23 种模式。通常提到的"24种"可能是包括了 GoF 的 23 种加上一个常被提及的补充模式(如空对象模式),或者是不同分类方式导致的计数差异。
- 可重用性:设计模式提供了可重用的解决方案
- 可维护性:使用设计模式使代码更易理解和维护
- 可扩展性:设计模式为代码提供了良好的扩展性
- 标准化:设计模式是经过验证的标准化解决方案
- 使用经过验证的解决方案,减少错误
- 代码结构更清晰,易于理解
- 提高代码的可读性和可维护性
- 避免重复造轮子
- 快速解决常见问题
- 减少调试时间
- 提供统一的编程语言和思维方式
- 便于团队成员之间的代码审查
- 提高代码的可读性和一致性
负责对象的创建,将对象的创建与使用分离。
模式 | 描述 | 应用场景 |
---|---|---|
单例模式(Singleton) | 确保一个类只有一个实例 | 数据库连接、配置管理 |
工厂模式(Factory) | 通过工厂类创建对象 | 根据条件创建不同类型的对象 |
抽象工厂模式(Abstract Factory) | 创建相关对象族 | 跨平台UI组件创建 |
建造者模式(Builder) | 分步骤构建复杂对象 | 复杂对象的创建过程 |
原型模式(Prototype) | 通过克隆创建对象 | 对象创建成本高时 |
关注类和对象的组合,建立对象间的结构关系。
模式 | 描述 | 应用场景 |
---|---|---|
适配器模式(Adapter) | 让不兼容的接口能够合作 | 集成第三方库 |
桥接模式(Bridge) | 将抽象与实现分离 | 多维度变化的设计 |
组合模式(Composite) | 将对象组合成树形结构 | 文件系统、UI组件树 |
装饰器模式(Decorator) | 动态地给对象添加功能 | 中间件、过滤器 |
外观模式(Facade) | 为子系统提供统一接口 | 简化复杂系统的使用 |
享元模式(Flyweight) | 共享细粒度对象 | 大量相似对象的内存优化 |
代理模式(Proxy) | 控制对其他对象的访问 | 远程代理、虚拟代理 |
关注对象间的通信,描述对象如何协作完成任务。
模式 | 描述 | 应用场景 |
---|---|---|
责任链模式(Chain of Responsibility) | 将请求的发送者和接收者解耦 | 异常处理、审批流程 |
命令模式(Command) | 将请求封装成对象 | 撤销/重做、宏命令 |
解释器模式(Interpreter) | 为语言创建解释器 | 表达式解析、DSL |
迭代器模式(Iterator) | 提供访问集合元素的方法 | 遍历复杂数据结构 |
中介者模式(Mediator) | 封装对象间的交互 | 聊天室、GUI组件交互 |
备忘录模式(Memento) | 保存和恢复对象状态 | 撤销功能、游戏存档 |
观察者模式(Observer) | 定义对象间的一对多依赖关系 | 事件处理、数据绑定 |
状态模式(State) | 让对象在内部状态改变时改变行为 | 状态机、游戏角色状态 |
策略模式(Strategy) | 定义算法族,分别封装起来 | 算法选择、支付方式 |
模板方法模式(Template Method) | 定义算法骨架,子类实现具体步骤 | 框架设计、算法模板 |
访问者模式(Visitor) | 在不改变类结构的前提下定义新操作 | 编译器、序列化 |
本项目将展示各种设计模式在 Go 语言中的实现示例,包括:
- ✅ 完整的代码示例
- 📝 使用场景说明
- ⚖️ 优缺点分析
- 🎯 实际应用案例
design-patterns-go/
├── creational/ # 创建型模式
│ ├── singleton/ # 单例模式
│ ├── factory/ # 工厂模式
│ ├── abstract_factory/# 抽象工厂模式
│ ├── builder/ # 建造者模式
│ └── prototype/ # 原型模式
├── structural/ # 结构型模式
│ ├── adapter/ # 适配器模式
│ ├── bridge/ # 桥接模式
│ ├── composite/ # 组合模式
│ ├── decorator/ # 装饰器模式
│ ├── facade/ # 外观模式
│ ├── flyweight/ # 享元模式
│ └── proxy/ # 代理模式
├── behavioral/ # 行为型模式
│ ├── chain_of_responsibility/ # 责任链模式
│ ├── command/ # 命令模式
│ ├── interpreter/ # 解释器模式
│ ├── iterator/ # 迭代器模式
│ ├── mediator/ # 中介者模式
│ ├── memento/ # 备忘录模式
│ ├── observer/ # 观察者模式
│ ├── state/ # 状态模式
│ ├── strategy/ # 策略模式
│ ├── template_method/ # 模板方法模式
│ └── visitor/ # 访问者模式
├── examples/ # 实际应用示例
│ ├── web_framework/ # Web框架设计模式应用
│ ├── database/ # 数据库操作设计模式
│ └── middleware/ # 中间件设计模式
├── docs/ # 文档
│ ├── patterns/ # 各模式详细说明
│ └── best_practices/ # 最佳实践
└── README.md # 项目说明
- 循序渐进:从简单的模式开始学习
- 实践为主:多写代码,多思考应用场景
- 理解原理:不仅要知道怎么用,更要理解为什么这样设计
- 结合实际:在项目中尝试使用设计模式
- 持续学习:设计模式是编程的重要基础,需要不断学习和实践
- 入门级:单例、工厂、策略、观察者
- 进阶级:装饰器、适配器、模板方法、状态
- 高级级:责任链、命令、访问者、中介者
- 先写简单代码,再考虑重构
- 遵循"三振法则"
- 记录使用设计模式的原因
- 团队内部统一设计模式的使用规范
记住:设计模式是工具,不是目的。合适的场景下使用,不合适的时候保持简单。