深入 Spring 源码,剖析设计模式的落地实践
# 写在文章开头
阅读源码是理解框架最有效的方式之一,Spring 源码中蕴含了大量设计模式的经典应用。本文将从源码层面深入剖析这些设计模式,带你理解框架设计精髓,掌握在实际项目中灵活运用的能力。
你好,我是 SharkChili ,Java Guide 核心维护者之一,对 Redis、Nightingale 等知名开源项目有深度源码研究经验。熟悉 Java、Go、C 等多语言技术栈,现任某知名黑厂高级开发工程师,专注于高并发系统架构设计与性能优化。
🌟 开源项目贡献
- mini-redis:教学级 Redis 精简实现,助力分布式缓存原理学习
🔗 https://github.com/shark-ctrl/mini-redis (opens new window)(欢迎 Star & Contribute)
📚 公众号价值 分享企业级架构设计、性能优化、源码解析等核心技术干货,涵盖分布式系统、微服务治理、大数据处理等实战领域,并探索面向AI的vibe coding等现代开发范式。
👥 加入技术社群 关注公众号,回复 【加群】 获取联系方式,与众多技术爱好者交流分布式架构、微服务等前沿技术!
# 设计模式的七大原则
我们先来简单回顾一下设计模式的七大原则:
# 1. 开闭原则
对扩展开放,对修改关闭。即在不修改现有代码的前提下,通过扩展来增加新功能。
反例:假如有一个图形绘制功能,最初只支持圆形,我们可能会这样写:
public class GraphicEditor {
public void drawShape(String shapeType) {
if ("circle".equals(shapeType)) {
System.out.println("绘制圆形");
} else if ("rectangle".equals(shapeType)) {
System.out.println("绘制矩形");
}
}
}
2
3
4
5
6
7
8
9
这种方式每新增一种图形,都需要修改 drawShape 方法,违反了开闭原则。
正例:使用接口抽象,遵循开闭原则:
// 定义抽象接口
public interface Shape {
void draw();
}
// 新增圆形,无需修改现有代码
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 新增矩形,只需扩展,无需修改Shape接口或其他实现类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2. 里氏转换原则
子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法,确保父类出现的地方子类都能正确替换。
反例:将"鸟"作为父类,让会飞的企鹅也继承它:
// 父类:鸟
public class Bird {
public void fly() {
System.out.println("鸟在飞");
}
}
// 企鹅不会飞,重写fly()抛异常,违反里氏转换
public class Penguin extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("企鹅不会飞");
}
}
// 使用时
Bird bird = new Penguin();
bird.fly(); // 运行时抛出异常!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
这种方式的问题在于:企鹅 is-a 鸟,但企鹅不会飞,导致父类出现的地方子类无法正确替换。
正例:引入更抽象的父类,正确建模:
// 更抽象的父类:动物
public class Animal {
}
// 会飞的动物
public class FlyingBird extends Animal {
public void fly() {
System.out.println("鸟在飞");
}
}
// 麻雀继承会飞的鸟
public class Sparrow extends FlyingBird {
// 直接继承fly()方法
}
// 企鹅继承动物,但不会飞
public class Penguin extends Animal {
// 不会继承fly()方法
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这样每个子类都能正确替换其父类,符合里氏转换原则。
这种问题的根源在于:fly() 方法并不适用于所有"鸟"子类。
正确做法:当父类的方法在某些子类中不适用时,应该抽象出更细粒度的父类,让有共同行为的子类继承它,而不是强行让所有子类都继承父类所有方法。
类图如下:
Animal(抽象)
/ \
FlyingBird Penguin
|
Sparrow
2
3
4
5
# 3. 依赖倒置原则
高层模块不应该依赖底层模块,两者都应该依赖其抽象。
其中"抽象"指接口或抽象类,"细节"指具体实现类。高层模块通常是业务逻辑层(如 UserService),底层模块是数据访问层(如 MySQLUserDao)。
如下图,实现者MySQLUserDao依赖抽象接口UserDao限定自己的行为规范实现基于id的查询,高层UserService依赖抽象接口将接口实现类UserDao聚合,抽象不应依赖细节,细节应依赖抽象

对应代码示例:
// 错误:高层类直接依赖底层实现
public class UserService {
private MySQLUserDao userDao = new MySQLUserDao(); // 直接依赖具体实现
}
// 正确:高层类依赖抽象接口
public class UserService {
private UserDao userDao; // 依赖抽象
public UserService(UserDao userDao) {
this.userDao = userDao; // 通过构造器注入
}
}
public interface UserDao {
User findById(Long id);
}
// 底层实现依赖抽象
public class MySQLUserDao implements UserDao {
@Override
public User findById(Long id) {
// MySQL 具体查询逻辑
return jdbcTemplate.queryForObject(
"SELECT * FROM user WHERE id = ?", id);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 4. 合成复用原则
通过继承关系实现软件复用会使得子类被迫继承父类所有方法,即使不需要也要全部接受,可控性较差。尽量使用对象组合/聚合,按需实现委托代码:
反例的问题:UserService extends LoggerService 会让 UserService 被迫继承 LoggerService 的所有 public/protected 方法,即使 UserService 根本不需要这些功能。这会导致:
- 类膨胀:继承了不需要的方法
- 行为污染:客户端可能误调用不该暴露的方法

// 日志接口
public interface Logger {
void log(String message);
}
// 日志实现类
public class LoggerService implements Logger {
@Override
public void log(String message) {
System.out.println(message);
}
}
// 错误:通过继承复用Logger功能
public class UserService extends LoggerService {
public void doSomething() {
log("操作日志"); // 继承得到的方法
}
}
// 正确:通过组合复用Logger功能
public class UserService {
private Logger logger; // 组合
public UserService(Logger logger) {
this.logger = logger;
}
public void doSomething() {
logger.log("操作日志");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 5. 单一职责原则
一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。
// 错误:一个类承担多个职责
public class UserManager {
public void addUser(User user) { /* 用户管理 */ }
public void sendEmail(String msg) { /* 邮件发送 */ }
public void generateReport() { /* 报表生成 */ }
}
// 正确:职责分离
public class UserManager {
public void addUser(User user) { /* 仅用户管理 */ }
}
public class EmailService {
public void sendEmail(String msg) { /* 仅邮件发送 */ }
}
public class ReportService {
public void generateReport() { /* 仅报表生成 */ }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 6. 接口隔离原则
用多个专门的接口,而不是单一的总接口,客户端不应该依赖它不需要的接口。
// 错误:一个臃肿的总接口
public interface IAnimal {
void eat();
void fly();
void swim();
}
// 正确:接口隔离,按能力拆分
public interface IEat {
void eat();
}
public interface IFly {
void fly();
}
public interface ISwim {
void swim();
}
// 狗只会吃和游泳
public class Dog implements IEat, ISwim {
@Override
public void eat() { }
@Override
public void swim() { }
}
// 鸟会吃和飞
public class Bird implements IEat, IFly {
@Override
public void eat() { }
@Override
public void fly() { }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 7. 迪米特法则
最少知道原则,一个类应该尽可能减少对其他类的了解,只与直接的朋友(成员变量、方法参数、方法返回值)通信

// 错误:Teacher直接访问Student的Course内部细节
public class Teacher {
public void checkCourse(Student student) {
List<Course> courses = student.getCourses(); // 知道了Student内部有Course列表
for (Course course : courses) {
System.out.println(course.getName());
}
}
}
// 正确:Teacher只与Student交互,不关心其内部细节
public class Teacher {
public void checkCourse(Student student) {
student.showCourseInfo(); // 让Student自己暴露需要的信息
}
}
public class Student {
private List<Course> courses;
public void showCourseInfo() {
for (Course course : courses) {
System.out.println(course.getName());
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 设计模式分类概览
# 创建型模式
创建型模式主要用于创建对象,对应的设计模式有:
# 1. 单例模式
确保类有且只有一个对象被创建,全局单例。
DCL双重锁校验模式(JDK 1.5前主流写法,现已过时):
public class Singleton {
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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DCL在JDK 1.5之后才真正安全有效,之前因instance = new Singleton()指令重排存在漏洞。
主流推荐:通过JVM类加载机制安全发布
// 饿汉式:类加载时立即初始化,JVM保证线程安全
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
// Holder模式:延迟加载 + JVM线程安全(推荐)
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
// 枚举单例:最简洁安全,JVM天然保证唯一性(最佳实践)
public enum Singleton {
INSTANCE;
public void doSomething() { }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
根据《Java并发编程实战》推荐:应利用JVM类加载机制保证线程安全,而非依赖复杂的同步机制。枚举单例因JVM底层支持,是目前最简洁安全的单例实现方式。
# 2. 抽象工厂模式
允许客户创建对象的族,而无需指定他们的具体类。
// 抽象工厂
public interface GUIFactory {
Button createButton();
CheckBox createCheckBox();
}
// Windows工厂族
public class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public CheckBox createCheckBox() { return new WindowsCheckBox(); }
}
// Mac工厂族
public class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public CheckBox createCheckBox() { return new MacCheckBox(); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3. 建造者模式
将一个复杂对象的构建与它的表示分离,让同样的构建过程可以创建不同的表示。
public class Computer {
private String cpu;
private String ram;
private String storage;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
}
public static class Builder {
private String cpu;
private String ram;
private String storage;
public Builder cpu(String cpu) { this.cpu = cpu; return this; }
public Builder ram(String ram) { this.ram = ram; return this; }
public Builder storage(String storage) { this.storage = storage; return this; }
public Computer build() { return new Computer(this); }
}
}
// 使用
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.ram("16GB")
.storage("512GB SSD")
.build();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 4. 工厂方法模式
由子类决定要创建的具体类是哪一个。Spring中的FactoryBean就是工厂方法模式的典型实现。
通用工厂方法模式:
// 抽象工厂
public abstract class LoggerFactory {
public abstract Logger createLogger();
}
// 具体工厂:创建文件日志
public class FileLoggerFactory extends LoggerFactory {
public Logger createLogger() { return new FileLogger(); }
}
// 具体工厂:创建数据库日志
public class DatabaseLoggerFactory extends LoggerFactory {
public Logger createLogger() { return new DatabaseLogger(); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Spring中的FactoryBean(文章后续章节详细介绍):
public interface CreateObjStrategy {
Object createObj();
}
@Component("createObj_str")
public class CreateStrObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() { return "Hello"; }
}
@Component("createObj_json")
public class CreateJsonObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() { return new JSONObject(); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 5. 原型模式
用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
public class Prototype implements Cloneable {
private String name;
private List<String> items;
public Prototype(String name) {
this.name = name;
this.items = new ArrayList<>();
}
@Override
public Prototype clone() {
Prototype copy = new Prototype(this.name);
copy.items = new ArrayList<>(this.items); // 深拷贝
return copy;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 结构型模式
结构型模式主要用于处理不同类之间的组合与依赖关系,对应的设计模式有:
- 适配器模式:封装对象,并提供不同的接口。
- 桥接模式:将抽象部分和实现部分分离,让他们独立的变化。
- 装饰模式:包装一个对象,提供新的行为。
- 组合模式:客户用一致的方式处理对象集合和单个对象。
- 外观模式:简化一群类的接口。
- 享元模式:运用共享技术有效的支持大量细粒度的对象。
- 代理模式:包装对象,以控制对此对象的访问。
# 1. 适配器模式 (Adapter)
设计思路: 继承目标接口获取目标行为,将被适配者的逻辑嵌入到实现类内部,通过委托方式完成接口转换。
代码示例:
// 目标接口:客户端期望的欧式充电
public interface EuropeanCharger {
void chargeWithEuropeanPlug();
}
// 被适配者:已有的美式充电器(无法修改)
public class AmericanCharger {
public void chargeWithAmericanPlug() {
System.out.println("使用美式插头充电");
}
}
// 适配器:继承目标接口获取欧式行为,内部持有美式充电器
public class ChargerAdapter extends AmericanCharger implements EuropeanCharger {
@Override
public void chargeWithEuropeanPlug() {
// 将欧式请求转换为美式逻辑
chargeWithAmericanPlug();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
应用场景: Spring HandlerAdapter;旧系统接口兼容;USB转Type-C转换器。
# 2. 桥接模式 (Bridge)
设计思路: 将抽象部分与实现部分分离,通过组合而非继承连接两者,使两者可以独立扩展。
核心结构: 抽象类持有实现接口的引用,具体子类通过该引用调用实现方法。
应用场景: 不同平台 × 不同图形(如 JDBC 驱动);跨平台 GUI 框架。
# 3. 装饰模式 (Decorator)
设计思路: 继承目标接口获取目标行为,内部持有被装饰对象,在方法前后添加增强逻辑。
代码示例:
// 组件接口:定义核心行为
public interface DataSource {
void write(String data);
String read();
}
// 具体组件:基础文件操作
public class FileDataSource implements DataSource {
private String filename;
public FileDataSource(String filename) {
this.filename = filename;
}
@Override
public void write(String data) {
System.out.println("写入文件:" + data);
}
@Override
public String read() {
return "文件内容";
}
}
// 装饰器基类:继承接口获取行为,内部持有被装饰对象
public class DataSourceDecorator implements DataSource {
protected DataSource wrappee; // 被包装对象
public DataSourceDecorator(DataSource wrappee) {
this.wrappee = wrappee;
}
@Override
public void write(String data) {
wrappee.write(data); // 默认委托
}
@Override
public String read() {
return wrappee.read(); // 默认委托
}
}
// 具体装饰:加密增强
public class EncryptionDecorator extends DataSourceDecorator {
public EncryptionDecorator(DataSource wrappee) {
super(wrappee); // 注入被装饰对象
}
@Override
public void write(String data) {
super.write("加密(" + data + ")"); // 增强写操作
}
@Override
public String read() {
return "解密(" + super.read() + ")"; // 增强读操作
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
应用场景: Java I/O流;Spring BeanWrapper;请求/响应包装;日志增强。
# 4. 组合模式 (Composite)
设计思路: 继承组件接口获取一致行为,叶子节点直接实现业务,容器节点管理子组件并委托处理。
代码示例:
// 组件接口:定义一致行为
public interface Component {
int getPrice();
}
// 叶子节点:单个产品,直接实现业务
public class Product implements Component {
private String name;
private int price;
public Product(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public int getPrice() {
return price;
}
}
// 容器节点:箱子,继承接口获取一致行为,管理子组件
public class Box implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
@Override
public int getPrice() {
// 将请求委托给子组件,最后汇总
return children.stream().mapToInt(Component::getPrice).sum();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
应用场景: 文件系统目录结构;组织架构树;菜单与菜单项;UI组件树。
# 5. 外观模式 (Facade)
设计思路: 继承客户端期望的接口获取行为,内部聚合多个子系统,将复杂调用封装为简单方法。
代码示例:
// 子系统:CPU
public class CPU {
public void start() { System.out.println("CPU启动"); }
}
// 子系统:内存
public class Memory {
public void load() { System.out.println("加载数据到内存"); }
}
// 子系统:硬盘
public class Disk {
public void read() { System.out.println("从硬盘读取数据"); }
}
// 外观类:继承客户端接口,内部聚合子系统
public class ComputerFacade implements Computer {
private CPU cpu = new CPU();
private Memory memory = new Memory();
private Disk disk = new Disk();
@Override
public void start() {
cpu.start();
memory.load();
disk.read();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
应用场景: Spring ApplicationContext;医院挂号窗口;第三方SDK封装。
# 6. 享元模式 (Flyweight)
设计思路: 将对象分为内部状态(可共享)和外部状态(不可共享),通过工厂管理享元池复用内部状态相同的对象。
核心结构: 享元工厂维护享元池,根据外部参数返回已有对象或创建新对象。
应用场景: 字符串常量池;Word 字符渲染;线程池、数据库连接池。
# 7. 代理模式 (Proxy)
设计思路: 继承目标接口获取目标行为,内部持有真实对象,在调用前后添加访问控制逻辑。
代码示例:
// 主题接口:定义真实对象的行为
public interface Image {
void display();
}
// 真实对象:真正加载图片
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk(); // 模拟耗时加载
}
private void loadFromDisk() {
System.out.println("从磁盘加载大图:" + filename);
}
@Override
public void display() {
System.out.println("显示图片:" + filename);
}
}
// 代理对象:继承接口获取行为,内部持有真实对象
public class ImageProxy implements Image {
private RealImage realImage;
private String filename;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
// 按需延迟加载真实对象
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
应用场景: Spring AOP;MyBatis懒加载;Spring Data JPA;图片延迟加载;安全代理。
# 行为型模式
行为型模式主要用于描述对类或对象怎样交互和怎样分配职责,对应的设计模式有:
- 模板方法模式:定义一个操作算法的总体架构,将一些步骤的实现放在子类中。
- 命令模式:封装请求成为对象。
- 迭代器模式:在对象的集合之中游走,而不是暴露集合的实现。
- 观察者模式:让对象能够在状态改变时被通知。
- 中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显示的相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
- 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 以后就可以将该对象恢复到保存状态。
- 解释器模式:介绍给定一个语言,定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
- 状态模式:封装了基于状态的行为,并使用委托在行为之间的切换。
- 策略模式:封装可以互换的行为,并使用委托来决定要使用哪一个。
- 责任链模式:为了解除请求的发送者和接收者之间的耦合,使多个对象都有机会处理这个请求。将这些处理对象连成一个链,并沿着这个链传递该请求,直到一个对象处理它。
- 访问者模式:一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
# 1. 模板方法模式 (Template Method)
设计思路: 继承抽象类获取算法骨架,在父类中定义步骤顺序,子类只需实现具体步骤。
代码示例:
// 抽象父类:定义算法骨架
public abstract class DataMiner {
// 模板方法:定义算法骨架,声明为final防止重写
public final void mine() {
openFile();
extractData();
parseData();
analyzeData();
sendReport();
closeFile();
}
// 通用方法
protected void openFile() { System.out.println("打开文件"); }
protected void closeFile() { System.out.println("关闭文件"); }
protected void sendReport() { System.out.println("发送报告"); }
// 抽象方法:子类必须实现
protected abstract void extractData();
protected abstract void parseData();
protected abstract void analyzeData();
}
// 具体子类:实现PDF步骤
public class PDFDataMiner extends DataMiner {
@Override
protected void extractData() { System.out.println("从PDF提取数据"); }
@Override
protected void parseData() { System.out.println("解析PDF格式"); }
@Override
protected void analyzeData() { System.out.println("分析PDF数据"); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
应用场景: Spring AbstractApplicationContext.refresh();JUnit测试框架;Hibernate Session模板。
# 2. 命令模式 (Command)
设计思路: 继承命令接口获取执行能力,内部持有接收者,将调用者与执行者解耦。
代码示例:
// 命令接口:定义执行能力
public interface Command {
void execute();
}
// 接收者:知道如何执行具体操作
public class Light {
public void on() { System.out.println("灯打开"); }
public void off() { System.out.println("灯关闭"); }
}
// 具体命令:继承接口获取执行能力,内部持有接收者
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
@Override
public void execute() { light.on(); }
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) { this.light = light; }
@Override
public void execute() { light.off(); }
}
// 调用者:持有命令对象
public class RemoteControl {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void press() { command.execute(); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
应用场景: Spring TransactionTemplate;GUI按钮;数据库事务命令;菜单项。
# 3. 观察者模式 (Observer)
设计思路: 继承观察者接口获取通知能力,注册到主题,主题状态变化时通知所有观察者。
代码示例:
// 主题接口:定义订阅能力
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyAllObservers();
}
// 具体主题:继承接口获取通知能力
public class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>();
private int temperature;
@Override
public void attach(Observer observer) { observers.add(observer); }
@Override
public void detach(Observer observer) { observers.remove(observer); }
@Override
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update(temperature);
}
}
public void setTemperature(int temperature) {
this.temperature = temperature;
notifyAllObservers();
}
}
// 观察者接口:定义接收通知能力
public interface Observer {
void update(int temperature);
}
// 具体观察者:继承接口获取通知能力
public class DisplayBoard implements Observer {
private String name;
public DisplayBoard(String name) { this.name = name; }
@Override
public void update(int temperature) {
System.out.println(name + " 显示温度:" + temperature);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
应用场景: Spring ApplicationEvent;Spring MVC 事件机制;GUI事件监听。
# 4. 策略模式 (Strategy)
设计思路: 继承策略接口获取算法能力,通过注入不同策略实现算法切换。
代码示例:
// 策略接口:定义算法能力
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略:继承接口获取算法能力
public class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
public CreditCardPayment(String cardNumber) { this.cardNumber = cardNumber; }
@Override
public void pay(double amount) { System.out.println("信用卡支付:" + amount); }
}
public class AlipayPayment implements PaymentStrategy {
@Override
public void pay(double amount) { System.out.println("支付宝支付:" + amount); }
}
// 上下文:持有策略,委托执行
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout() {
double total = items.stream().mapToDouble(Item::getPrice).sum();
paymentStrategy.pay(total);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
应用场景: Spring Resource;订单定价策略;支付方式选择;排序算法切换。
# 5. 责任链模式 (Chain of Responsibility)
设计思路: 继承处理器接口获取处理能力,内部持有下一个处理器,形成链式处理。
代码示例:
// 处理器接口:定义处理能力
public abstract class Handler {
private Handler nextHandler;
public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; }
public final void handleRequest(Request request) {
if (canHandle(request)) {
doHandle(request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
} else {
System.out.println("无法处理请求");
}
}
protected abstract boolean canHandle(Request request);
protected abstract void doHandle(Request request);
}
// 具体处理器:继承接口获取处理能力
public class AuthHandler extends Handler {
@Override
protected boolean canHandle(Request request) { return request.needAuth(); }
@Override
protected void doHandle(Request request) { System.out.println("认证处理"); }
}
public class ValidationHandler extends Handler {
@Override
protected boolean canHandle(Request request) { return request.needValidation(); }
@Override
protected void doHandle(Request request) { System.out.println("参数校验"); }
}
public class BusinessHandler extends Handler {
@Override
protected boolean canHandle(Request request) { return true; }
@Override
protected void doHandle(Request request) { System.out.println("业务处理"); }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
应用场景: Spring Security过滤器链;Spring MVC拦截器;日志级别处理;审批流程。
Netty Pipeline 典型运用:
// Netty中的ChannelHandlerContext就是责任链中的上下文
public class ChannelHandlerContext {
private final ChannelPipeline pipeline;
private final String name;
private final ChannelHandler handler;
// 传递给下一个处理器
public ChannelHandlerContext fireChannelRead(Object msg) {
final AbstractChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ);
next.invokeChannelRead(msg);
return next;
}
}
// 入站处理器示例
public class LoggingHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("收到消息:" + msg);
ctx.fireChannelRead(msg); // 传递给下一个入站处理器
}
}
// 出站处理器示例
public class Encoder extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ByteBuf encoded = encode(ctx, (ByteBuf) msg);
ctx.write(encoded, promise); // 传递给下一个出站处理器
}
}
// Pipeline组装
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline()
.addLast("decoder", new MyDecoder()) // 入站:解码
.addLast("encoder", new MyEncoder()) // 出站:编码
.addLast("logging", new LoggingHandler())// 入站:日志
.addLast("handler", new MyBusinessHandler()); // 入站:业务处理
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 6. 迭代器模式 (Iterator)
简要说明: 提供一种方法顺序访问集合元素,而不暴露集合的内部表示。Java已内置迭代器支持。
应用场景: Java Iterator、ListIterator;Spring RowMapper遍历结果集。
# 7. 中介者模式 (Mediator)
简要说明: 用一个中介对象封装一系列对象交互,将网状依赖关系转为星型耦合。
应用场景: Spring Controller协调各服务;GUI对话框组件通信。
# 8. 备忘录模式 (Memento)
简要说明: 捕获对象内部状态并保存到外部,需要时恢复对象状态。
应用场景: 数据库事务回滚;Git版本控制;游戏存档。
# 9. 解释器模式 (Interpreter)
简要说明: 定义语法表示和解释器,解释特定语言中的句子。
应用场景: Spring SpEL表达式;正则表达式引擎;SQL解析器。
# 10. 状态模式 (State)
简要说明: 封装基于状态的行为,通过委托在行为之间切换,替代大量条件判断。
应用场景: 订单状态机;TCP连接状态管理;工作流审批。
# 11. 访问者模式 (Visitor)
简要说明: 在不改变元素类的前提下定义作用于元素的新操作,适合数据结构稳定但操作多变的场景。
应用场景: Java FileVisitor;编译器语法树遍历;XML文档结构处理。
# 详解Spring几种经典的设计模式
# 1. 简单工厂模式
简单工厂模式的思想是对外屏蔽创建对象的细节,将对象的获取统一内聚到一个工厂类中。这一思想在 Spring 中的 ApplicationContext 体现得淋漓尽致。
Spring 通过 BeanFactory 统一管理 Bean 的创建和获取,使用时只需通过上下文传入对应的 Bean 名称即可获取所需对象,无需关心对象创建细节:

对应的我们也给出使用示例:
@Autowired
private ApplicationContext applicationContext;
public Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
2
3
4
5
6
# 2. 工厂方法模式
工厂方法模式适用于让工厂专注于创建单一类型对象的场景。相较于简单工厂模式,工厂方法模式提供工厂接口,开发者根据规范创建不同工厂,按需使用不同工厂创建不同类。这种做法确保了工厂类遵循开闭原则。
Spring 中的 FactoryBean 就是工厂方法模式的典型实现。如果希望容器提供一个可以创建指定类型对象的工厂,可通过 FactoryBean 实现。
例如需要工厂创建经理和主管两类雇员,由于两者都是雇员类,首先创建雇员类:
public class EmployeeDTO {
private Integer id;
private String firstName;
private String lastName;
private String designation;
// getters and setters...
}
2
3
4
5
6
7
8
然后继承 FactoryBean 接口实现工厂方法类,通过传入的 designation 决定创建的雇员类型:
public class EmployeeFactoryBean extends AbstractFactoryBean<Object> {
private String designation;
public void setDesignation(String designation) {
this.designation = designation;
}
@Override
protected Object createInstance() throws Exception {
EmployeeDTO employee = new EmployeeDTO();
employee.setId(-1);
employee.setFirstName("dummy");
employee.setLastName("dummy");
employee.setDesignation(designation);
return employee;
}
@Override
public Class<EmployeeDTO> getObjectType() {
return EmployeeDTO.class;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
两种雇员的配置如下:
<!-- 经理工厂 -->
<bean id="manager" class="com.study.service.EmployeeFactoryBean">
<property name="designation" value="Manager" />
</bean>
<!-- 主管工厂 -->
<bean id="director" class="com.study.service.EmployeeFactoryBean">
<property name="designation" value="Director" />
</bean>
2
3
4
5
6
7
8
获取 Bean 时需注意:使用 & 前缀获取的是工厂本身,不加则获取工厂创建的对象:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 获取工厂本身
Object factory = context.getBean("&director");
System.out.println(((EmployeeFactoryBean) factory).getObject());
// 直接获取工厂创建的对象
EmployeeDTO manager = (EmployeeDTO) context.getBean("manager");
EmployeeDTO director = (EmployeeDTO) context.getBean("director");
2
3
4
5
6
7
8
9
# 3. 单例模式
Spring 默认将所有 Bean 的作用域设置为单例,具体实现在 DefaultSingletonBeanRegistry 的 getSingleton 方法中,通过三级缓存解决单例 Bean 的创建和循环依赖问题,具体实现已在创建型模式章节中详细讲解。
# 4. 代理模式
代理模式解耦了调用者与被代理对象的关系,通过对目标对象进行代理实现功能增强,易于拓展和维护。Spring AOP 就是通过代理模式实现增强切入,Spring 同时支持 JDK 动态代理和 CGLIB 两种方式,下面以 JDK 代理为例说明:
public Object getProxy(@Nullable ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
2
3
4
5
Proxy.newProxyInstance 内部通过反射获取代理类类型和 InvocationHandler,完成代理类创建:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//......
//获取接口类类型
Class<?> cl = getProxyClass0(loader, intfs);
//......
//从缓存中获取代理类的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//......
//基于InvocationHandler 和构造方法完成代理类创建
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
//......
} catch (InvocationTargetException e) {
//......
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 5. 模板方法模式
模板方法模式固定算法骨架,抽象可变方法交给子类实现。Spring 的 AbstractApplicationContext.refresh() 方法就是典型模板方法模式:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
try {
// 已实现好的细节,通过回调调用用户实现
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
// 模板方法体现:用户可自定义重写
onRefresh();
} catch (BeansException ex) {
throw ex;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 6. 观察者模式
观察者模式定义主题与订阅者之间的依赖关系,当主题状态发生改变时,通知所有订阅者并触发响应操作。
Spring 事件驱动模型就是观察者模式的经典应用。在很多场景下都可以通过该模式解耦代码,例如发布通知后需要用户做出响应时,就可以利用观察者模式解决。
首先定义事件类:
public class DemoEvent extends ApplicationEvent {
private String msg;
public DemoEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public String getMsg() { return msg; }
}
2
3
4
5
6
7
8
9
10
然后创建监听器,实现 ApplicationListener 接口对 DemoEvent 进行监听:
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
private static Logger logger = LoggerFactory.getLogger(DemoListener.class);
@Override
public void onApplicationEvent(DemoEvent event) {
logger.info("收到消息: {}", event.getMsg());
}
}
2
3
4
5
6
7
8
9
发布事件后,监听器自动接收并处理:
@Autowired
private ApplicationContext applicationContext;
@Test
public void sendMsg() {
DemoEvent event = new DemoEvent(this, "你好");
applicationContext.publishEvent(event);
}
2
3
4
5
6
7
8
输出结果:
2022-11-22 13:03:15.814 INFO --- DemoListener : 收到消息: 你好
# 7. 适配器模式
适配器模式应用在 DisposableBeanAdapter 统一处理 Bean 销毁上。Bean 销毁有两种方式:
- XML 配置指定 Bean 及方法名
- 继承
DisposableBean接口实现
两种方式的处理逻辑不同,Spring 通过 DisposableBeanAdapter 进行统一适配。DisposableBeanAdapter 组合了目标 Bean 和销毁方式,适配器根据不同的销毁场景选择合适的调用逻辑:

DisposableBeanAdapter 构造方法根据传入的 Bean 类型判断走接口调用还是配置调用:
public DisposableBeanAdapter(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {
this.invokeDisposableBean = (this.bean instanceof DisposableBean);
}
2
3
调用 destroy 时,适配器根据 invokeDisposableBean 决定销毁逻辑:
@Override
public void destroy() {
// 接口实现方式
if (this.invokeDisposableBean) {
try {
((DisposableBean) this.bean).destroy();
} catch (Throwable ex) {
// handle exception
}
}
// XML或注解配置方式
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 8. 装饰者模式
装饰者模式通过组合方式扩展原有类行为,是遵循开闭原则的结构型设计模式。Spring 中的 TransactionAwareCacheDecorator 是装饰者模式的典型应用,它继承缓存接口并组合目标缓存类,在不修改原类的情况下实现事务支持的扩展:
public class TransactionAwareCacheDecorator implements Cache {
private final Cache targetCache;
@Override
public void put(final Object key, @Nullable final Object value) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
}
});
} else {
this.targetCache.put(key, value);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 关于设计模式的一些常见问题
# 为什么说Spring框架中的IOC是解耦的
从代码层面来说,Spring 通过控制反转将对象之间依赖关系交由容器管理,如下所示我们的AService 依赖BService ,BService 可能还会依赖于CService 层层递进,如果是传统编码,我们可能需要通过硬编码的方式完成AService 的构建。
而Spring通过IOC思想,在初始化阶段将所有对象都交由三级缓存管理,将所有java bean初始化责任的实现细节转移给Spring,使用时也只需指明接口类型,接口实现也无需关心,只需在配置层面中指定,而非通过硬编码完成依赖管理:

所以我们使用时只需几个简单的配置和注解即可完成各种复杂的bean的依赖管理,这也就是开发层面对象依赖关系管理的解耦:
@Service("aService")
@Slf4j
public class AService {
@Autowired
private BService bService;
//......
}
2
3
4
5
6
7
8
9
10
从使用层面来说,Spring中的IOC也用到类似于门面模式的思想,将工具类的使用和创建剥离,整个工具类的创建过程对使用者来说是透明解耦的。
例如我们需要使用日志框架,在spring中我们只需给出简单的配置,框架即在运行时基于给定配置完成对应的日志工具的注入(可以是log4j可以是slf4j或者其他日志框架),程序启动后即可直接使用功能,无需关心创建和实现:

# 什么是策略模式
策略模式是一种行为模式,它的作用主要是封装那些行为一致、但具体实现不同的场景。例如我们现在有一个审核的动作,不同的人审核的方式不同。而且审核的行为会随着时间推移不断增加,单纯使用if else去维护会使得代码变得非常凌乱。
这时候使用策略模式定义一下相同的行为,让子类去实现不同的策略,这样的方式是最利于拓展的。
使用策略模式前,我们先需要使用接口固定一下策略的定义,例如我们现在要创建一个生成对象的策略createObj:
public interface CreateObjStrategy {
Object createObj();
}
2
3
4
对应我们分别写一个创建字符串对象和json对象的策略代码:
@Component("createObj_str")
public class CreateStrObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() {
Map<String, Object> map = new HashMap<>();
map.put("name", "xiaoming");
return JSONUtil.toJsonStr(map);
}
}
@Component("createObj_json")
public class CreateJsonObjStrategy implements CreateObjStrategy {
@Override
public Object createObj() {
JSONObject obj = new JSONObject();
obj.put("name", "zhangsan");
return obj;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
到此为止,我们已经完成了所有的策略的封装,按照原生的策略模式的做法它会通过一个上下文来配置当前策略,就像下面这张设计图:

对应我们给出封装的代码示例:
public class CreateJsonObjContext {
private CreateObjStrategy createObjStrategy;
public CreateJsonObjContext(CreateObjStrategy strategy) {
this.createObjStrategy = strategy;
}
public Object createObj() {
return createObjStrategy.createObj();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
实际上有了Spring我们无需进行显式声明创建了,我们可以通过配置、注解等方式指明本地程序需要注入的CreateObjStrategy 实现,加载上下文的时候通过ApplicationContextAware这样的扩展点把bean取出来设置到CreateJsonObjContext 中:
@Component
public class CreateJsonObjContext implements ApplicationContextAware {
private CreateObjStrategy createObjStrategy;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//从容器中拿到由我们配置后容器中所设置的CreateObjStrategy设置到Context中
CreateObjStrategy bean = applicationContext.getBean(CreateObjStrategy.class);
createObjStrategy = bean;
}
public Object createObj() {
return createObjStrategy.createObj();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Spring中哪里用到了策略模式
最典型的就是 InstantiationStrategy,Spring 为其实现了两种策略:CglibSubclassingInstantiationStrategy 和 SimpleInstantiationStrategy。Spring 在实例化 Bean 时,通过 getInstantiationStrategy 获取初始化策略,然后调用其 instantiate 方法完成 Bean 创建:

AbstractAutowireCapableBeanFactory 中的 instantiate 方法印证了这一点:
private Object instantiate(String beanName, RootBeanDefinition mbd,
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
try {
return this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
} catch (Throwable ex) {
throw new BeanCreationException(...);
}
}
2
3
4
5
6
7
8
9
# 工厂方法模式相较于简单工厂模式的优缺点
优点:
- 符合开闭原则,无需因增加类型而修改工厂代码,只需实现新的工厂类。
- 符合单一职责原则,单个类型的创建逻辑更易于维护。
缺点:
- 每个类型都需要创建对应工厂,类数量增加,项目可能变得臃肿。
- 模式结构导致维护成本相对较高。
# 单例模式在Java中的使用优势
- 节省对象创建时间:单例对象创建一次后可重复使用,避免重量级对象创建耗费大量资源。
- 降低 GC 压力:减少对象创建次数,避免不必要的 GC,从而减少 GC 停顿(Stop the World)。
# 模板方法模式的优劣势
优势:
- 算法骨架由父类定义,封装不变,扩展可变。
- 子类只需按需实现抽象方法,易于扩展维护。
- 提取公共代码,避免重复编写。
劣势:
- 可能导致类层次结构复杂,可读性下降。
- 继承方式可能导致子类泛滥。
# 案例实践:基于Spring框架的支付策略模式
# 一、背景说明
在实际业务中,我们常常需要对接多个支付渠道(支付宝、微信、银联等)。为了保持开闭原则和可维护性,我们借助 Spring ApplicationContext 实现天然的简单工厂,封装各个支付策略完成不同渠道的付款逻辑。
核心设计思路:
- 策略模式:定义统一支付接口,每种支付渠道单独实现
- 简单工厂:借助 Spring 容器,根据Bean名称获取对应策略实现
- 开闭原则:新增支付渠道只需添加实现类,无需修改现有代码
# 二、代码清单
# 1. 策略接口
public interface PayStrategy {
void pay(double amount);
}
2
3
# 2. 支付宝策略
@Component("alipay")
public class AlipayStrategy implements PayStrategy {
@Override
public void pay(double amount) {
System.out.println("支付宝支付: ¥" + amount);
}
}
2
3
4
5
6
7
# 3. 微信支付策略
@Component("wechat")
public class WechatStrategy implements PayStrategy {
@Override
public void pay(double amount) {
System.out.println("微信支付: ¥" + amount);
}
}
2
3
4
5
6
7
# 4. 客户端调用
@Service
public class PaymentService {
@Autowired
private ApplicationContext applicationContext;
public void pay(String payType, double amount) {
PayStrategy strategy = applicationContext.getBean(payType, PayStrategy.class);
strategy.pay(amount);
}
}
2
3
4
5
6
7
8
9
10
11
# 三、涉及的设计模式
| 模式 | 体现位置 | 说明 |
|---|---|---|
| 策略模式 | PayStrategy 接口及其实现类 | 定义支付算法族,分别封装起来,让它们可以互相替换 |
| 简单工厂 | ApplicationContext.getBean() | 根据Bean名称从容器获取实例,屏蔽对象创建细节 |
| 依赖注入 | @Component + @Autowired | 对象创建交给 Spring 容器,实现控制反转 |
# 四、模式关系图
┌─────────────────────────────────────────────────────────┐
│ 客户端 (PaymentService) │
│ pay(payType, amount) │
│ │
│ String payType = "alipay"; ◄── 运行时决定策略 │
│ PayStrategy strategy = context.getBean(payType); │
│ strategy.pay(amount); │
└─────────────────────────┬───────────────────────────────┘
│ 调用
▼
┌─────────────────────────────────────────────────────────┐
│ Spring容器 (简单工厂 + 策略注册中心) │
│ applicationContext.getBean() │
│ 根据Bean名称获取对应策略实例(简单工厂) │
└─────────────────────────┬───────────────────────────────┘
│ 返回具体策略实例
▼
┌─────────────────────────────────────────────────────────┐
│ 策略接口 (Strategy) │
│ PayStrategy 接口 │
│ pay(double amount) │
└─────────────┬─────────────────────────────┬─────────────┘
│ 实现 │ 实现
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────┐
│ AlipayStrategy │ │ WechatStrategy │
│ @Component("alipay") │ │ @Component("wechat") │
│ │ │ │
│ pay(100.00) │ │ pay(100.00) │
│ → "支付宝支付: ¥100" │ │ → "微信支付: ¥100" │
└─────────────────────────┘ └─────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 五、核心设计意图
- 开闭原则:新增支付渠道只需添加策略实现类,无需修改
PaymentService - 消除条件分支:没有
if-else判断支付方式,通过Bean名称直接定位策略 - 简单工厂:借助 Spring 容器实现对象统一管理,屏蔽创建细节
- 单一职责:
PaymentService只负责调用策略,各策略自行实现支付逻辑
# 小结
本文从 Spring 源码层面剖析了设计模式的落地实践,主要涵盖以下内容:
创建型模式:工厂方法模式、单例模式、建造者模式、原型模式
结构型模式:适配器模式、装饰者模式、桥接模式、享元模式
行为型模式:策略模式、模板方法模式、观察者模式、代理模式
核心收获:
- 设计模式不是炫技,而是解决实际问题的最佳实践
- Spring 源码是学习设计模式的宝库,很多模式都有经典应用
- 理解模式的意图比记住结构更重要,活学活用才是关键
希望本文能帮助你在实际项目中更好地运用设计模式,写出优雅、易维护的代码。
你好,我是 SharkChili ,Java Guide 核心维护者之一,对 Redis、Nightingale 等知名开源项目有深度源码研究经验。熟悉 Java、Go、C 等多语言技术栈,现任某知名黑厂高级开发工程师,专注于高并发系统架构设计与性能优化。
🌟 开源项目贡献
- mini-redis:教学级 Redis 精简实现,助力分布式缓存原理学习
🔗 https://github.com/shark-ctrl/mini-redis (opens new window)(欢迎 Star & Contribute)
📚 公众号价值 分享企业级架构设计、性能优化、源码解析等核心技术干货,涵盖分布式系统、微服务治理、大数据处理等实战领域,并探索面向AI的vibe coding等现代开发范式。
👥 加入技术社群 关注公众号,回复 【加群】 获取联系方式,与众多技术爱好者交流分布式架构、微服务等前沿技术!
# 参考
观察者模式:https://www.runoob.com/design-pattern/observer-pattern.html (opens new window)
用一个简单的例子说明:为什么Spring/IoC能降低耦合度 :https://blog.csdn.net/Old_Secretary/article/details/137970675 (opens new window)
JAVA设计模式之门面模式(外观模式) :https://www.runoob.com/w3cnote/facade-pattern-3.html (opens new window)
Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂) :https://blog.csdn.net/a745233700/article/details/120253639 (opens new window)
一文彻底搞懂代理模式(Proxy) :https://blog.csdn.net/m0_51380306/article/details/119912574 (opens new window)
策略模式:https://www.runoob.com/design-pattern/strategy-pattern.html (opens new window)
一文搞懂策略模式(优化策略模式完全消除if else) :https://blog.csdn.net/bookssea/article/details/117043820 (opens new window)
UML一一 类图关系 (泛化、实现、依赖、关联、聚合、组合) :https://blog.csdn.net/m0_37989980/article/details/104470064 (opens new window)
策略模式 :https://www.runoob.com/design-pattern/strategy-pattern.html (opens new window)