23种设计模式深度解析:从原理到实战落地
前言
设计模式是软件开发中经过反复验证的最佳实践 ,是解决特定场景下代码设计问题的通用方案。掌握设计模式,能让我们的代码更具可复用性、可维护性和扩展性,同时也是从初级开发向中高级开发进阶的核心能力之一。本文将系统解析23种经典设计模式,按创建型、结构型、行为型三大分类展开,结合原理、适用场景、核心代码示例和流程图,让每一种模式的设计思路和落地方式清晰可见,助力开发者在实际项目中灵活运用。
一、设计模式概述
1.1 设计模式的定义
设计模式是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。它不是现成的代码,而是一种设计思想和代码组织策略,能指导开发者在面对特定问题时,做出更优的设计决策。
1.2 三大分类及核心宗旨
23种设计模式根据解决的问题类型,分为三大类,各自的核心目标不同:
- 创建型模式 :聚焦对象的创建过程,隐藏对象创建的复杂细节,实现创建与使用的解耦,让代码更灵活地应对对象创建的变化。
- 结构型模式 :关注类和对象的组合方式,通过合理的结构设计,实现类/对象之间的高效协作,提升系统的灵活性和复用性。
- 行为型模式 :侧重对象之间的交互和职责分配,规范对象之间的通信方式,让行为的实现更清晰、可扩展。
23种设计模式
5种
单例模式
工厂方法模式
抽象工厂模式
建造者模式
原型模式
7种
代理模式
适配器模式
装饰器模式
桥接模式
外观模式
组合模式
享元模式
11种
策略模式
模板方法模式
观察者模式
迭代器模式
责任链模式
命令模式
备忘录模式
状态模式
访问者模式
中介者模式
解释器模式
1.3 设计模式的核心原则
所有设计模式均基于面向对象的七大设计原则 (单一职责、开闭原则、里氏替换、依赖倒置、接口隔离、迪米特法则、合成复用)设计,其中开闭原则(对扩展开放,对修改关闭) 是贯穿所有模式的核心思想。
二、创建型模式(5种)
创建型模式共包含单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式 5种,核心解决对象创建的复杂性问题。以下是每种模式的详细解析,附核心流程图和代码示例(以Java为例,通用思路适用于Python/Go/C++等语言)。
2.1 单例模式
核心原理
保证一个类仅有一个实例,并提供一个全局访问点。
适用场景
配置文件管理、数据库连接池、日志对象、缓存等需要全局唯一实例的场景。
核心流程图
Created with Raphaël 2.3.0 程序启动 实例是否已创建? 返回已创建的实例 获取实例完成 创建唯一实例(私有化构造方法,禁止外部new) yes no
核心代码(懒汉式-线程安全)
java
public class Singleton {
// 私有化实例,volatile保证可见性和禁止指令重排
private static volatile Singleton instance;
// 私有化构造方法,禁止外部创建
private Singleton(){}
// 全局访问点,双重检查锁实现线程安全
public static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
关键要点
单例模式有饿汉式、懒汉式、静态内部类、枚举 等实现方式,枚举是最安全的实现(防止反射和序列化破坏单例)。
2.2 工厂方法模式
核心原理
定义一个创建对象的抽象方法,让子类决定实例化哪个类,将对象的创建延迟到子类。
适用场景
需要根据不同条件创建不同对象,且对象的创建逻辑较为简单的场景(如日志框架中创建不同的日志记录器)。
核心流程图
工厂1
工厂2
客户端请求创建对象
选择工厂
具体工厂1
具体工厂2
创建产品1
创建产品2
客户端使用产品
操作完成
核心要点
相比简单工厂模式,工厂方法模式更符合开闭原则,新增产品时只需新增具体工厂和具体产品,无需修改原有代码。
2.3 抽象工厂模式
核心原理
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用场景
需要创建一套配套的对象(如UI框架中,Windows风格的按钮、文本框、下拉框为一套,Mac风格为另一套)。
核心关键词
产品族 (同一工厂生产的一系列产品)、产品等级(不同工厂生产的同类型产品)。
2.4 建造者模式
核心原理
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用场景
创建复杂对象(如实体类有大量属性,且部分属性可选、创建步骤固定),如订单对象、汽车对象的创建。
核心角色
抽象建造者、具体建造者、指挥者、产品。指挥者控制构建流程,具体建造者实现具体的构建步骤。
2.5 原型模式
核心原理
通过复制已有实例来创建新的实例,而非通过new关键字创建,提升对象创建效率。
适用场景
创建对象的成本较高(如需要频繁访问数据库/网络获取初始化数据),且对象的属性大部分相同的场景。
核心要点
实现克隆接口 (如Java的Cloneable),分为浅克隆 (复制基本类型,引用类型指向原对象)和深克隆(复制基本类型+引用类型,创建全新对象)。
创建型模式总结
创建型模式的核心是解耦对象的创建和使用,不同模式的选择取决于对象的创建复杂度:简单唯一实例用单例,单一产品创建用工厂方法,配套产品创建用抽象工厂,复杂对象分步创建用建造者,对象创建成本高用原型。
三、结构型模式(7种)
结构型模式共包含代理模式、适配器模式、装饰器模式、桥接模式、外观模式、组合模式、享元模式 7种,核心解决类/对象的组合协作问题,通过合理的结构设计,让系统更灵活、更高效。
3.1 代理模式
核心原理
为其他对象提供一种代理以控制对这个对象的访问,在原对象的基础上增加额外的功能(如权限控制、日志、缓存)。
分类
静态代理、动态代理(JDK动态代理、CGLIB动态代理)、远程代理。
核心流程图(静态代理)
Created with Raphaël 2.3.0 客户端发起请求 代理类(执行前置操作:日志/权限校验) 目标类(执行核心业务逻辑) 代理类(执行后置操作:结果缓存/异常处理) 返回结果给客户端
适用场景
Spring AOP的底层实现、接口的权限控制、远程服务调用(RPC)、缓存代理等。
3.2 适配器模式
核心原理
将一个类的接口转换成客户希望的另一个接口,让原本因接口不兼容而无法一起工作的类能够协同工作。
分类
类适配器(继承)、对象适配器(组合,推荐使用)、接口适配器。
适用场景
集成第三方框架/组件(接口与项目不兼容)、老系统改造(兼容旧接口)。
核心类比
生活中的电源适配器(将220V交流电转换为5V直流电)。
3.3 装饰器模式
核心原理
动态地给一个对象添加额外的职责,而不改变其原有结构,相比继承更灵活。
适用场景
需要为对象动态添加功能,且功能可以灵活组合的场景(如Java IO中的FileReader+BufferedReader)。
核心要点
装饰器类和被装饰类实现同一接口,装饰器类持有被装饰类的引用。
3.4 桥接模式
核心原理
将抽象部分与它的实现部分分离,使它们都可以独立地变化,解决多层继承导致的类爆炸问题。
适用场景
一个类存在多个独立变化的维度(如手机:品牌维度+功能维度)。
3.5 外观模式
核心原理
为子系统中的一组接口提供一个统一的入口,简化客户端与子系统的交互,降低系统的耦合度。
适用场景
微服务中的网关层、项目中的工具类入口、第三方SDK的封装。
核心要点
外观类封装子系统的复杂逻辑,客户端只需与外观类交互,无需关注子系统的细节。
3.6 组合模式
核心原理
将对象组合成树形结构以表示"部分-整体"的层次关系,让客户端对单个对象和组合对象的使用保持一致。
适用场景
树形结构的场景(如文件夹与文件、组织架构、菜单导航)。
3.7 享元模式
核心原理
运用共享技术有效地支持大量细粒度的对象,减少对象的创建数量,降低内存消耗。
适用场景
系统中存在大量相同/相似对象(如棋盘游戏的棋子、数据库连接池、线程池)。
核心角色
享元工厂(管理享元对象池)、抽象享元、具体享元、非享元(不可共享的属性)。
结构型模式总结
结构型模式的核心是优化类/对象的结构,不同模式的选择取决于协作需求:控制对象访问用代理,兼容接口用适配器,动态添加功能用装饰器,分离多维度变化用桥接,简化子系统交互用外观,树形结构用组合,减少重复对象用享元。
四、行为型模式(11种)
行为型模式共包含策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式 11种,核心解决对象之间的交互和职责分配问题,规范通信方式,让行为更易扩展和维护。
4.1 策略模式
核心原理
定义一系列算法,将每个算法封装起来,并使它们可以相互替换,算法的变化独立于使用算法的客户。
核心流程图
策略1
策略2
客户端选择算法
上下文类
持有策略接口引用
抽象策略接口
具体策略1
实现算法1
具体策略2
实现算法2
上下文执行算法
返回算法结果
适用场景
排序算法、支付方式选择、日志存储方式(本地/数据库/云存储)等需要灵活切换算法/策略的场景。
4.2 模板方法模式
核心原理
定义一个操作中的算法骨架,将步骤的实现延迟到子类,让子类在不改变算法结构的情况下,重新定义算法的某些步骤。
适用场景
有固定执行流程,且部分步骤可定制的场景(如Spring的Bean生命周期、数据库的CRUD操作)。
4.3 观察者模式
核心原理
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
适用场景
发布-订阅模型、消息通知、事件监听(如Spring的事件机制、MQ消息队列)。
核心角色
主题(被观察者)、观察者、具体主题、具体观察者。
4.4 责任链模式
核心原理
为请求创建一个处理者链,请求沿着链传递,直到有一个处理者处理该请求,解耦请求的发送者和接收者。
适用场景
请求的多级处理(如权限校验、日志记录、异常处理的链式调用、Spring的拦截器链)。
4.5 命令模式
核心原理
将请求封装成一个对象,使你可以用不同的请求参数化其他对象,支持请求的排队、记录、撤销和重做。
适用场景
界面按钮的点击事件、远程控制、任务调度(如线程池的任务提交)。
4.6 其余行为型模式速览
| 模式名称 | 核心原理 | 典型场景 |
|---|---|---|
| 备忘录模式 | 在不破坏封装的前提下,捕获对象的内部状态并在外部保存,支持状态恢复 | 编辑器的撤销/重做、游戏的存档/读档 |
| 状态模式 | 将对象的状态封装为独立的类,让对象在不同状态下表现出不同的行为 | 订单状态流转(待支付/已支付/已发货/已完成)、电梯的状态控制 |
| 访问者模式 | 表示一个作用于某对象结构中的各元素的操作,可在不修改元素的前提下新增操作 | 数据结构的遍历与操作(如二叉树的遍历、报表生成) |
| 中介者模式 | 用一个中介对象封装一系列的对象交互,降低对象之间的耦合度 | 聊天室、微服务的服务注册中心、MVC的Controller |
| 迭代器模式 | 提供一种方法顺序访问一个聚合对象的各个元素,而不暴露其内部表示 | 集合框架的遍历(如Java的List/Set的iterator方法) |
| 解释器模式 | 定义语言的文法规则,并通过解释器解释语言中的句子 | 简单的表达式解析、SQL解析、正则表达式解析 |
行为型模式总结
行为型模式的核心是规范对象的交互方式,不同模式的选择取决于交互需求:灵活切换算法用策略,固定流程定制步骤用模板方法,一对多状态通知用观察者,请求多级处理用责任链,请求封装与撤销用命令。
五、23种设计模式整体总结
5.1 分类速记表
| 分类 | 包含模式(共23种) | 核心目标 |
|---|---|---|
| 创建型 | 单例、工厂方法、抽象工厂、建造者、原型(5种) | 解耦对象创建与使用 |
| 结构型 | 代理、适配器、装饰器、桥接、外观、组合、享元(7种) | 优化类/对象的组合结构 |
| 行为型 | 策略、模板方法、观察者、迭代器、责任链、命令、备忘录、状态、访问者、中介者、解释器(11种) | 规范对象的交互与职责分配 |
5.2 设计模式的使用原则
- 不要过度设计:只有当业务场景存在明确的变化点,且需要提升代码的可扩展性时,才使用设计模式,避免为了用模式而用模式。
- 理解本质而非形式:设计模式是思想,而非固定的代码模板,需结合具体语言和项目场景灵活调整(如Python中无需严格遵循接口,用鸭子类型即可)。
- 结合框架使用:主流框架(Spring、MyBatis、Django)均大量使用设计模式,学习框架的源码是理解设计模式最佳实践的方式。
- 遵循设计原则:设计模式是设计原则的具体实现,掌握七大设计原则,才能在无模式可参考时,设计出优秀的代码结构。
六、学习与实践建议
- 先掌握核心模式 :23种模式中,单例、代理、适配器、装饰器、策略、观察者、责任链是实际项目中使用频率最高的,优先掌握这些模式的原理和落地。
- 结合源码分析:分析Spring(AOP-代理模式、IOC-工厂模式)、MyBatis(工厂模式、代理模式、装饰器模式)、JDK源码(集合-迭代器模式、IO-装饰器模式)中的设计模式运用。
- 实战落地:在实际项目中尝试用设计模式解决具体问题(如用策略模式实现支付方式的灵活切换,用观察者模式实现消息通知)。
- 总结反思:使用设计模式后,复盘代码的可维护性、可扩展性是否得到提升,不断优化设计思路。
后记
设计模式是软件开发的通用语言 ,掌握它不仅能提升自己的代码设计能力,还能让团队之间的沟通更高效(如说"用单例模式实现",团队成员能快速理解设计思路)。但设计模式不是银弹,它解决的是通用问题,而实际项目中存在大量个性化的问题,需要我们结合业务场景,灵活运用甚至组合使用设计模式。