什么是设计模式?

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

设计模式的起源

设计模式的概念最早由建筑大师 Christopher Alexander 在建筑领域提出。1994年,Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,这四位作者也被称为”四人帮”(Gang of Four,简称 GoF)。

为什么要学习设计模式?

  1. 提升代码质量: 设计模式提供了经过验证的解决方案,可以避免常见的设计陷阱
  2. 增强代码可维护性: 使用设计模式能让代码结构更清晰,更易于维护和扩展
  3. 提高开发效率: 面对常见问题时,可以直接套用成熟的模式,无需从零开始
  4. 统一团队语言: 设计模式提供了一套标准的技术术语,便于团队沟通
  5. 深入理解框架源码: Spring、MyBatis 等主流框架大量使用了设计模式

设计模式的六大原则

在学习具体的设计模式之前,我们需要先了解面向对象设计的基本原则。这些原则是设计模式的理论基础。

1. 单一职责原则 (Single Responsibility Principle, SRP)

定义: 一个类应该只有一个引起它变化的原因。

解释: 一个类只负责一项职责,如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其他职责的能力。

1
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
// 不好的设计:一个类承担多个职责
class User {
private String name;
private String email;

// 用户数据管理
public void setName(String name) { this.name = name; }
public String getName() { return name; }

// 数据验证
public boolean validateEmail(String email) { /*...*/ }

// 数据持久化
public void saveToDatabase() { /*...*/ }

// 发送邮件通知
public void sendEmail() { /*...*/ }
}

// 好的设计:职责分离
class User {
private String name;
private String email;
// 只负责用户数据
}

class UserValidator {
public boolean validateEmail(String email) { /*...*/ }
}

class UserRepository {
public void save(User user) { /*...*/ }
}

class EmailService {
public void sendEmail(User user) { /*...*/ }
}

2. 开闭原则 (Open-Closed Principle, OCP)

定义: 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。

解释: 当需求变化时,应该通过扩展来实现变化,而不是通过修改已有的代码。

1
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
// 不好的设计:每次添加新图形都要修改计算类
class AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.radius * circle.radius;
} else if (shape instanceof Rectangle) {
Rectangle rect = (Rectangle) shape;
return rect.width * rect.height;
}
// 添加新图形需要修改这里
return 0;
}
}

// 好的设计:使用多态,添加新图形只需扩展
interface Shape {
double calculateArea();
}

class Circle implements Shape {
private double radius;

@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}

class Rectangle implements Shape {
private double width;
private double height;

@Override
public double calculateArea() {
return width * height;
}
}

// 添加新图形只需实现接口,无需修改已有代码
class Triangle implements Shape {
private double base;
private double height;

@Override
public double calculateArea() {
return 0.5 * base * height;
}
}

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

定义: 所有引用基类的地方必须能透明地使用其子类的对象。

解释: 子类可以扩展父类的功能,但不能改变父类原有的功能。子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

里氏是一个人名(Liskov,翻译为利斯科夫,简化为里氏)

1
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
// 违反里氏替换原则的例子
class Rectangle {
protected int width;
protected int height;

public void setWidth(int width) { this.width = width; }
public void setHeight(int height) { this.height = height; }
public int getArea() { return width * height; }
}

class Square extends Rectangle {
@Override
public void setWidth(int width) {
this.width = width;
this.height = width; // 正方形宽高相等
}

@Override
public void setHeight(int height) {
this.width = height;
this.height = height; // 正方形宽高相等
}
}

// 问题:期望面积为 50,实际得到 25
void test(Rectangle rect) {
rect.setWidth(5);
rect.setHeight(10);
assert rect.getArea() == 50; // 传入 Square 时会失败
}

4. 接口隔离原则 (Interface Segregation Principle, ISP)

定义: 客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。

解释: 建立单一接口,不要建立庞大臃肿的接口。接口应该尽量细化,同时接口中的方法应该尽量少。

1
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
// 不好的设计:臃肿的接口
interface Worker {
void work();
void eat();
void sleep();
}

class HumanWorker implements Worker {
public void work() { /*...*/ }
public void eat() { /*...*/ }
public void sleep() { /*...*/ }
}

class RobotWorker implements Worker {
public void work() { /*...*/ }
public void eat() { /* 机器人不需要吃饭 */ }
public void sleep() { /* 机器人不需要睡觉 */ }
}

// 好的设计:接口隔离
interface Workable {
void work();
}

interface Eatable {
void eat();
}

interface Sleepable {
void sleep();
}

class HumanWorker implements Workable, Eatable, Sleepable {
public void work() { /*...*/ }
public void eat() { /*...*/ }
public void sleep() { /*...*/ }
}

class RobotWorker implements Workable {
public void work() { /*...*/ }
}

5. 依赖倒置原则 (Dependency Inversion Principle, DIP)

定义: 高层模块不应该依赖低层模块,两者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。

解释: 面向接口编程,不要面向实现编程。

所属两者都应该依赖其抽象,再大白话补充一下,想象一个电源插座系统:

  • 抽象:国标插座接口(统一的标准)
  • 高层模块:你的手机充电器(依赖国标插座)
  • 低层模块:墙上的插座(实现国标标准)

“两者都依赖抽象”:

  • 充电器按照国标插座的标准设计插头(高层依赖抽象)
  • 墙上的插座按照国标标准设计插孔(低层依赖抽象)
  • 只要都遵守国标,任何充电器都能插任何插座

如果没有这个”抽象”(国标):

  • 每个充电器的插头形状不一样
  • 每个插座的插孔形状不一样
  • 完全无法通用!
1
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
// 不好的设计:高层依赖低层具体实现
class MySQLDatabase {
public void connect() { /*...*/ }
}

class UserService {
private MySQLDatabase database = new MySQLDatabase();

public void saveUser(User user) {
database.connect(); // 直接依赖具体实现
// 保存用户
}
}

// 好的设计:依赖抽象
interface Database {
void connect();
}

class MySQLDatabase implements Database {
public void connect() { /*...*/ }
}

class PostgreSQLDatabase implements Database {
public void connect() { /*...*/ }
}

class UserService {
private Database database; // 依赖抽象

public UserService(Database database) {
this.database = database;
}

public void saveUser(User user) {
database.connect();
// 保存用户
}
}

6. 迪米特法则 (Law of Demeter, LoD)

定义: 一个对象应该对其他对象有最少的了解,又称最少知识原则

解释: 一个类对自己依赖的类知道的越少越好,降低类之间的耦合度。

依赖地越多,耦合得越重。

1
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
// 不好的设计:过多的依赖链
class Customer {
public Wallet getWallet() { /*...*/ }
}

class Wallet {
public Money getMoney() { /*...*/ }
}

class Cashier {
public void charge(Customer customer, double amount) {
Wallet wallet = customer.getWallet(); // 了解 Customer 的内部结构
Money money = wallet.getMoney(); // 了解 Wallet 的内部结构
// 处理支付
}
}

// 好的设计:只与直接的朋友通信
class Customer {
private Wallet wallet;

public void pay(double amount) { // 封装内部细节
wallet.pay(amount);
}
}

class Cashier {
public void charge(Customer customer, double amount) {
customer.pay(amount); // 只与 Customer 交互
}
}

设计模式分类

GoF 将23种设计模式按照目的分为三大类:

创建型模式 (Creational Patterns)

创建型模式关注对象的创建过程,将对象的创建和使用分离,降低系统的耦合度。

  1. 单例模式 (Singleton Pattern)
  2. 工厂方法模式 (Factory Method Pattern)
  3. 抽象工厂模式 (Abstract Factory Pattern)
  4. 建造者模式 (Builder Pattern)
  5. 原型模式 (Prototype Pattern)

结构型模式 (Structural Patterns)

结构型模式关注类和对象的组合,通过继承和组合来获得更强大的功能。

  1. 适配器模式 (Adapter Pattern)
  2. 桥接模式 (Bridge Pattern)
  3. 组合模式 (Composite Pattern)
  4. 装饰器模式 (Decorator Pattern)
  5. 外观模式 (Facade Pattern)
  6. 享元模式 (Flyweight Pattern)
  7. 代理模式 (Proxy Pattern)

行为型模式 (Behavioral Patterns)

行为型模式关注对象之间的通信,明确对象之间的职责划分。

  1. 责任链模式 (Chain of Responsibility Pattern)
  2. 命令模式 (Command Pattern)
  3. 解释器模式 (Interpreter Pattern)
  4. 迭代器模式 (Iterator Pattern)
  5. 中介者模式 (Mediator Pattern)
  6. 备忘录模式 (Memento Pattern)
  7. 观察者模式 (Observer Pattern)
  8. 状态模式 (State Pattern)
  9. 策略模式 (Strategy Pattern)
  10. 模板方法模式 (Template Method Pattern)
  11. 访问者模式 (Visitor Pattern)

常用设计模式详解

GoF 的 23 种设计模式按照目的可以分为三大类:创建型模式(5种)、结构型模式(7种)、行为型模式(11种)。下面我们按照分类详细介绍这些模式。


创建型模式 (Creational Patterns)

创建型模式关注对象的创建过程,将对象的创建和使用分离,降低系统的耦合度。

单例模式 (Singleton Pattern - 创建型)

定义: 确保一个类只有一个实例,并提供一个全局访问点。

应用场景:

  • 配置管理器
  • 日志记录器
  • 数据库连接池
  • 线程池

实现方式:

懒汉式(线程不安全)
1
2
3
4
5
6
7
8
9
10
11
12
public class Singleton {
private static Singleton instance;

private Singleton() {}

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式(线程安全)
1
2
3
4
5
6
7
8
9
public class Singleton {
private static final Singleton instance = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return instance;
}
}
双重检查锁定(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}
}
静态内部类(推荐)
1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private Singleton() {}

private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

核心原理:

(1) 延迟加载(Lazy Loading)

- SingletonHolder 是一个静态内部类
- 类加载时机:静态内部类不会在外部类加载时就加载,只有在首次主动使用时才会被加载
- 当第一次调用 Singleton.getInstance() 时,JVM 才会加载 SingletonHolder 类
- 此时才会初始化 INSTANCE 变量,创建 Singleton 实例

(2) 线程安全性

- JVM 类加载机制保证:类的初始化阶段是线程安全的
- JVM 会保证一个类的 <clinit>() 方法(类初始化方法)在多线程环境下被正确加锁和同步
- 这意味着 INSTANCE 的初始化天然是线程安全的,无需额外的 synchronized

原理示意:
// 第一次调用 getInstance()
Singleton.getInstance()

访问 SingletonHolder.INSTANCE

触发 SingletonHolder 类加载

JVM 加锁,执行 () 方法

创建 Singleton 实例并赋值给 INSTANCE

返回 INSTANCE

// 后续调用 getInstance()

Singleton.getInstance()
    ↓
直接返回已创建的 SingletonHolder.INSTANCE

优点:

  • ✅ 延迟加载(懒加载)
  • ✅ 天然线程安全
  • ✅ 实现简洁
枚举(最佳实践)
1
2
3
4
5
6
7
public enum Singleton {
INSTANCE;

public void doSomething() {
// 业务方法
}
}

核心原理:

(1) JVM 层面的保证

枚举在 JVM 中被编译后,实际上会生成类似这样的代码:

public final class Singleton extends Enum {
public static final Singleton INSTANCE;

  static {
      INSTANCE = new Singleton("INSTANCE", 0);
  }

  private Singleton(String name, int ordinal) {
      super(name, ordinal);
  }

}

(2) 三大保证

① 线程安全

  • 枚举实例在类加载时创建,JVM 保证 () 方法的线程安全
  • 枚举值是 public static final 的,天然线程安全

② 防止反射攻击
// 尝试通过反射创建枚举实例会抛出异常
Constructor constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton instance = constructor.newInstance();
// 抛出 IllegalArgumentException: Cannot reflectively create enum objects

JVM 在 Constructor.newInstance() 方法中特别处理了枚举:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException(“Cannot reflectively create enum objects”);

③ 防止序列化破坏
// 即使序列化再反序列化,也保证是同一个实例
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“singleton.ser”));
oos.writeObject(Singleton.INSTANCE);
oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“singleton.ser”));
Singleton instance = (Singleton) ois.readObject();

System.out.println(instance == Singleton.INSTANCE); // true

枚举的反序列化有特殊处理,ObjectInputStream 会通过枚举名称查找已存在的实例,而不是创建新实例。

实际应用
1
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
// Spring 中的单例 Bean
@Component
public class ConfigManager {
// Spring 默认以单例方式管理 Bean
}

// 日志记录器
public class Logger {
private static volatile Logger instance;

private Logger() {}

public static Logger getInstance() {
if (instance == null) {
synchronized (Logger.class) {
if (instance == null) {
instance = new Logger();
}
}
}
return instance;
}

public void log(String message) {
System.out.println("[" + LocalDateTime.now() + "] " + message);
}
}

工厂模式 (Factory Pattern - 创建型)

定义: 定义一个创建对象的接口,让子类决定实例化哪一个类。

应用场景:

  • 对象创建逻辑复杂
  • 需要根据不同条件创建不同对象
  • 隐藏对象的创建细节

简单工厂模式:

1
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
// 产品接口
interface Product {
void use();
}

// 具体产品
class ProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}

class ProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}

// 简单工厂
class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ProductA();
case "B":
return new ProductB();
default:
throw new IllegalArgumentException("未知产品类型");
}
}
}

// 使用
Product product = SimpleFactory.createProduct("A");
product.use();

工厂方法模式:

1
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
// 产品接口
interface Product {
void use();
}

// 具体产品
class ProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}

class ProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}

// 工厂接口
interface Factory {
Product createProduct();
}

// 具体工厂
class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}

class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}

// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();
product.use();

实际应用:

1
2
3
4
5
6
7
8
9
10
11
// JDBC 中的工厂模式
Connection conn = DriverManager.getConnection(url, user, password);

// Spring 中的工厂模式
@Configuration
public class BeanFactory {
@Bean
public UserService userService() {
return new UserServiceImpl();
}
}

建造者模式 (Builder Pattern - 创建型)

定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

应用场景:

  • 对象有很多属性,部分必填部分可选
  • 对象创建过程复杂,需要多个步骤
  • 避免构造函数参数过多

实现示例:

1
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 产品类
class Computer {
// 必需参数
private String cpu;
private String memory;

// 可选参数
private String hardDisk;
private String graphics;
private String monitor;
private String keyboard;

// 私有构造函数
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.hardDisk = builder.hardDisk;
this.graphics = builder.graphics;
this.monitor = builder.monitor;
this.keyboard = builder.keyboard;
}

// 静态内部建造者类
public static class Builder {
// 必需参数
private String cpu;
private String memory;

// 可选参数(默认值)
private String hardDisk = "500G";
private String graphics = "集成显卡";
private String monitor = "普通显示器";
private String keyboard = "普通键盘";

// 必需参数通过构造函数传入
public Builder(String cpu, String memory) {
this.cpu = cpu;
this.memory = memory;
}

// 可选参数通过链式调用设置
public Builder hardDisk(String hardDisk) {
this.hardDisk = hardDisk;
return this;
}

public Builder graphics(String graphics) {
this.graphics = graphics;
return this;
}

public Builder monitor(String monitor) {
this.monitor = monitor;
return this;
}

public Builder keyboard(String keyboard) {
this.keyboard = keyboard;
return this;
}

// 构建对象
public Computer build() {
return new Computer(this);
}
}

@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", hardDisk='" + hardDisk + '\'' +
", graphics='" + graphics + '\'' +
", monitor='" + monitor + '\'' +
", keyboard='" + keyboard + '\'' +
'}';
}
}

// 使用:链式调用,清晰易读
Computer computer1 = new Computer.Builder("Intel i7""16G")
.hardDisk("1T SSD")
.graphics("RTX 3080")
.monitor("4K 显示器")
.keyboard("机械键盘")
.build();

Computer computer2 = new Computer.Builder("Intel i5""8G")
.hardDisk("512G SSD")
.build(); // 其他使用默认值

System.out.println(computer1);
System.out.println(computer2);

实际应用:

1
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
// StringBuilder (建造者模式的简化版)
StringBuilder sb = new StringBuilder()
.append("Hello")
.append(" ")
.append("World");

// Lombok 的 @Builder 注解
@Builder
public class User {
private String name;
private int age;
private String email;
}
// 使用
User user = User.builder()
.name("张三")
.age(25)
.email("zhangsan@example.com")
.build();

// OkHttp 的 Request
Request request = new Request.Builder()
.url("https://api.example.com")
.header("Authorization""Bearer token")
.post(body)
.build();

结构型模式 (Structural Patterns)

结构型模式关注类和对象的组合,通过继承和组合来获得更强大的功能。

适配器模式 (Adapter Pattern - 结构型)

定义: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。

应用场景:

  • 旧系统接口改造
  • 第三方库接口适配
  • 多个接口统一

形象比喻: 就像电源转换插头,把中国的两孔插头转换成美国的三孔插座标准。

实现示例:

1
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
// 目标接口(客户期望的接口)
interface MediaPlayer {
void play(String audioType, String fileName);
}

// 被适配者(旧接口)
class AdvancedMediaPlayer {
public void playVlc(String fileName) {
System.out.println("播放 VLC 文件: " + fileName);
}

public void playMp4(String fileName) {
System.out.println("播放 MP4 文件: " + fileName);
}
}

// 适配器
class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedPlayer;

public MediaAdapter(String audioType) {
this.advancedPlayer = new AdvancedMediaPlayer();
}

@Override
public void play(String audioType, String fileName) {
if ("vlc".equalsIgnoreCase(audioType)) {
advancedPlayer.playVlc(fileName);
} else if ("mp4".equalsIgnoreCase(audioType)) {
advancedPlayer.playMp4(fileName);
}
}
}

// 客户端代码
class AudioPlayer implements MediaPlayer {
private MediaAdapter adapter;

@Override
public void play(String audioType, String fileName) {
// 内置支持 mp3
if ("mp3".equalsIgnoreCase(audioType)) {
System.out.println("播放 MP3 文件: " + fileName);
}
// 使用适配器支持其他格式
else if ("vlc".equalsIgnoreCase(audioType) || "mp4".equalsIgnoreCase(audioType)) {
adapter = new MediaAdapter(audioType);
adapter.play(audioType, fileName);
} else {
System.out.println("不支持的格式: " + audioType);
}
}
}

// 使用
MediaPlayer player = new AudioPlayer();
player.play("mp3""song.mp3");
player.play("mp4""video.mp4");
player.play("vlc""movie.vlc");

实际应用:

1
2
3
4
5
// Java IO 中的适配器: 将字节流转换为字符流
Reader reader = new InputStreamReader(new FileInputStream("file.txt"));

// Spring MVC 中的 HandlerAdapter
// 将不同类型的 Handler 适配为统一的调用方式

装饰器模式 (Decorator Pattern - 结构型)

定义: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。

应用场景:

  • 需要动态地给对象添加功能
  • 需要大量的子类扩展时
  • IO 流的包装

实现示例:

1
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 组件接口
interface Coffee {
double getCost();
String getDescription();
}

// 具体组件
class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 10.0;
}

@Override
public String getDescription() {
return "普通咖啡";
}
}

// 装饰器基类
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;

public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}

@Override
public double getCost() {
return coffee.getCost();
}

@Override
public String getDescription() {
return coffee.getDescription();
}
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}

@Override
public double getCost() {
return super.getCost() + 2.0; // 行为被改变了,这是它和静态代理模式的区别
}

@Override
public String getDescription() {
return super.getDescription() + " + 牛奶"; // 行为被改变了
}
}

class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}

@Override
public double getCost() {
return super.getCost() + 1.0;
}

@Override
public String getDescription() {
return super.getDescription() + " + 糖";
}
}

class ChocolateDecorator extends CoffeeDecorator {
public ChocolateDecorator(Coffee coffee) {
super(coffee);
}

@Override
public double getCost() {
return super.getCost() + 3.0;
}

@Override
public String getDescription() {
return super.getDescription() + " + 巧克力";
}
}

// 使用
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元");

coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元");

coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元");

coffee = new ChocolateDecorator(coffee);
System.out.println(coffee.getDescription() + " - " + coffee.getCost() + "元");

实际应用:

1
2
3
4
5
6
7
// Java IO 流就是装饰器模式的经典应用
InputStream in = new FileInputStream("file.txt");
in = new BufferedInputStream(in);
in = new DataInputStream(in);

// Spring 中的 BeanWrapper
BeanWrapper wrapper = new BeanWrapperImpl(user);

代理模式 (Proxy Pattern - 结构型)

定义: 为其他对象提供一种代理以控制对这个对象的访问。

应用场景:

  • 远程代理(RPC)
  • 虚拟代理(延迟加载)
  • 保护代理(权限控制)
  • 智能引用(日志、缓存等)

静态代理:

1
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
// 接口
interface UserService {
void saveUser(String username);
}

// 真实对象
class UserServiceImpl implements UserService {
@Override
public void saveUser(String username) {
System.out.println("保存用户: " + username);
}
}

// 代理对象
class UserServiceProxy implements UserService {
private UserService userService;

public UserServiceProxy(UserService userService) {
this.userService = userService;
}

@Override
public void saveUser(String username) {
System.out.println("[代理] 权限检查");
System.out.println("[代理] 开始事务");

userService.saveUser(username);

System.out.println("[代理] 提交事务");
System.out.println("[代理] 记录日志");
}
}

// 使用
UserService userService = new UserServiceImpl();
UserService proxy = new UserServiceProxy(userService);
proxy.saveUser("张三");

动态代理(JDK):

1
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
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 接口
interface UserService {
void saveUser(String username);
void deleteUser(String username);
}

// 真实对象
class UserServiceImpl implements UserService {
@Override
public void saveUser(String username) {
System.out.println("保存用户: " + username);
}

@Override
public void deleteUser(String username) {
System.out.println("删除用户: " + username);
}
}

// 动态代理处理器
class ServiceInvocationHandler implements InvocationHandler {
private Object target;

public ServiceInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("[动态代理] 方法调用前: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("[动态代理] 方法调用后: " + method.getName());
return result;
}
}

// 使用
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new ServiceInvocationHandler(userService)
);

proxy.saveUser("张三");
proxy.deleteUser("李四");

实际应用:

1
2
3
4
5
6
7
8
9
10
11
// Spring AOP 就是基于代理模式实现的
@Service
public class UserService {
@Transactional // 通过代理实现事务管理
public void saveUser(User user) {
// 保存用户
}
}

// MyBatis 的 Mapper 接口也是通过动态代理实现的
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

外观模式 (Facade Pattern - 结构型) 也叫做门面模式

定义: 为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。

应用场景:

  • 简化复杂系统的接口
  • 为多个子系统提供统一入口
  • 解耦客户端和子系统

形象比喻: 就像酒店前台,你不需要直接联系客房部、餐饮部、保洁部,只需要告诉前台你的需求,前台会协调各部门为你服务。

实现示例:

1
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 子系统1:音响
class Stereo {
public void on() {
System.out.println("音响打开");
}

public void off() {
System.out.println("音响关闭");
}

public void setVolume(int volume) {
System.out.println("音量设置为: " + volume);
}
}

// 子系统2:投影仪
class Projector {
public void on() {
System.out.println("投影仪打开");
}

public void off() {
System.out.println("投影仪关闭");
}

public void setInput(String input) {
System.out.println("投影仪输入设置为: " + input);
}
}

// 子系统3:灯光
class Lights {
public void dim(int level) {
System.out.println("灯光调暗至: " + level + "%");
}

public void on() {
System.out.println("灯光打开");
}
}

// 子系统4:DVD 播放器
class DvdPlayer {
public void on() {
System.out.println("DVD 播放器打开");
}

public void off() {
System.out.println("DVD 播放器关闭");
}

public void play(String movie) {
System.out.println("播放电影: " + movie);
}
}

// 外观类:家庭影院
class HomeTheaterFacade {
private Stereo stereo;
private Projector projector;
private Lights lights;
private DvdPlayer dvdPlayer;

public HomeTheaterFacade() {
this.stereo = new Stereo();
this.projector = new Projector();
this.lights = new Lights();
this.dvdPlayer = new DvdPlayer();
}

// 一键观影
public void watchMovie(String movie) {
System.out.println("准备观影...");
lights.dim(10);
projector.on();
projector.setInput("DVD");
stereo.on();
stereo.setVolume(5);
dvdPlayer.on();
dvdPlayer.play(movie);
System.out.println("开始播放!");
}

// 一键结束
public void endMovie() {
System.out.println("关闭影院...");
dvdPlayer.off();
stereo.off();
projector.off();
lights.on();
System.out.println("影院已关闭");
}
}

// 使用:简化操作
HomeTheaterFacade homeTheater = new HomeTheaterFacade();
homeTheater.watchMovie("阿凡达");
// ... 观影中 ...
homeTheater.endMovie();

实际应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SLF4J 日志门面
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.info("这是日志"); // 底层可能是 Logback、Log4j 等

// Spring 的 ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 隐藏了复杂的 Bean 加载、依赖注入等细节

// JDBC 工具类
public class DbUtils {
public static void executeUpdate(String sql, Object... params) {
// 封装了获取连接、创建 Statement、执行 SQL、关闭资源等复杂操作
}
}

行为型模式 (Behavioral Patterns)

行为型模式关注对象之间的通信,明确对象之间的职责划分。

策略模式 (Strategy Pattern - 行为型)

定义: 定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。

应用场景:

  • 多个算法只在行为上稍有不同
  • 需要动态切换算法
  • 避免使用多重条件判断

实现示例:

1
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
62
63
64
65
66
67
68
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}

// 具体策略
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;

public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}

@Override
public void pay(double amount) {
System.out.println("使用信用卡 " + cardNumber + " 支付 " + amount + " 元");
}
}

class AlipayPayment implements PaymentStrategy {
private String account;

public AlipayPayment(String account) {
this.account = account;
}

@Override
public void pay(double amount) {
System.out.println("使用支付宝账户 " + account + " 支付 " + amount + " 元");
}
}

class WeChatPayment implements PaymentStrategy {
private String openId;

public WeChatPayment(String openId) {
this.openId = openId;
}

@Override
public void pay(double amount) {
System.out.println("使用微信 " + openId + " 支付 " + amount + " 元");
}
}

// 上下文
class ShoppingCart {
private PaymentStrategy paymentStrategy;

public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}

public void checkout(double amount) {
if (paymentStrategy == null) {
throw new IllegalStateException("未选择支付方式");
}
paymentStrategy.pay(amount);
}
}

// 使用
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new AlipayPayment("user@example.com"));
cart.checkout(100.0);

cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
cart.checkout(200.0);

实际应用:

1
2
3
4
5
6
7
// Comparator 就是策略模式的典型应用
List<String> list = Arrays.asList("apple""banana""cherry");

// 使用不同的排序策略
Collections.sort(list, Comparator.naturalOrder());
Collections.sort(list, Comparator.reverseOrder());
Collections.sort(list, Comparator.comparing(String::length));

观察者模式 (Observer Pattern - 行为型)

定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

应用场景:

  • 事件处理系统
  • 消息订阅系统
  • MVC 架构中的模型-视图关系

实现示例:

1
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
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.util.ArrayList;
import java.util.List;

// 观察者接口
interface Observer {
void update(String message);
}

// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}

// 具体主题
class NewsPublisher implements Subject {
private List<Observer> observers = new ArrayList<>();
private String latestNews;

@Override
public void attach(Observer observer) {
observers.add(observer);
}

@Override
public void detach(Observer observer) {
observers.remove(observer);
}

@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(latestNews);
}
}

public void publishNews(String news) {
this.latestNews = news;
System.out.println("发布新闻: " + news);
notifyObservers();
}
}

// 具体观察者
class NewsReader implements Observer {
private String name;

public NewsReader(String name) {
this.name = name;
}

@Override
public void update(String message) {
System.out.println(name + " 收到新闻: " + message);
}
}

// 使用
NewsPublisher publisher = new NewsPublisher();

Observer reader1 = new NewsReader("张三");
Observer reader2 = new NewsReader("李四");
Observer reader3 = new NewsReader("王五");

publisher.attach(reader1);
publisher.attach(reader2);
publisher.attach(reader3);

publisher.publishNews("重大新闻:设计模式很重要!");

publisher.detach(reader2);

publisher.publishNews("最新消息:观察者模式已掌握!");

实际应用:

1
2
3
4
5
6
7
8
9
10
11
// Spring 的事件机制就是观察者模式
@Component
public class UserEventListener {
@EventListener
public void handleUserCreated(UserCreatedEvent event) {
System.out.println("用户创建: " + event.getUsername());
}
}

// JDK 中的 Observable 和 Observer (已过时,但仍是经典示例)
// 现代应用推荐使用 Spring Event 或 RxJava

模板方法模式 (Template Method Pattern - 行为型)

定义: 在一个方法中定义算法的骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。

应用场景:

  • 多个类有相同的处理流程(相同的生命周期),但具体步骤不同
  • 框架设计(定义流程,由用户实现细节)
  • 代码复用

实现示例:

1
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
// 抽象类:定义模板方法
abstract class DataProcessor {
// 模板方法:定义算法骨架(final 防止子类修改)
public final void process() {
readData();
processData();
saveData();
}

// 抽象方法:由子类实现
protected abstract void readData();
protected abstract void processData();

// 具体方法:通用实现
protected void saveData() {
System.out.println("保存处理后的数据");
}
}

// 具体类1:处理 CSV 数据
class CsvDataProcessor extends DataProcessor {
@Override
protected void readData() {
System.out.println("从 CSV 文件读取数据");
}

@Override
protected void processData() {
System.out.println("处理 CSV 数据");
}
}

// 具体类2:处理 XML 数据
class XmlDataProcessor extends DataProcessor {
@Override
protected void readData() {
System.out.println("从 XML 文件读取数据");
}

@Override
protected void processData() {
System.out.println("处理 XML 数据");
}
}

// 使用
DataProcessor csvProcessor = new CsvDataProcessor();
csvProcessor.process();
// 输出:
// 从 CSV 文件读取数据
// 处理 CSV 数据
// 保存处理后的数据

DataProcessor xmlProcessor = new XmlDataProcessor();
xmlProcessor.process();
// 输出:
// 从 XML 文件读取数据
// 处理 XML 数据
// 保存处理后的数据

实际应用:

1
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
// Spring 的 JdbcTemplate
public class JdbcTemplate {
public <T> T query(String sql, ResultSetExtractor<T> rse) {
// 模板方法定义流程
Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
T result = rse.extractData(rs); // 由用户实现具体逻辑
closeResources();
return result;
}
}

// Servlet 的生命周期方法
public abstract class HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp) {
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, resp); // 由子类实现
} else if (method.equals("POST")) {
doPost(req, resp); // 由子类实现
}
}

protected abstract void doGet(HttpServletRequest req, HttpServletResponse resp);
protected abstract void doPost(HttpServletRequest req, HttpServletResponse resp);
}

责任链模式 (Chain of Responsibility Pattern - 行为型)

定义: 为请求创建一个接收者对象的链,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把请求传给下一个接收者,依此类推。

应用场景:

  • 多个对象可以处理同一请求,但具体由哪个对象处理在运行时动态决定
  • 需要动态指定处理请求的对象集合
  • 过滤器链、拦截器链

实现示例:

1
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// 抽象处理者
abstract class ApprovalHandler {
protected ApprovalHandler nextHandler;
protected String name;

public ApprovalHandler(String name) {
this.name = name;
}

// 设置下一个处理者
public void setNextHandler(ApprovalHandler nextHandler) {
this.nextHandler = nextHandler;
}

// 处理请求
public abstract void handleRequest(int amount);
}

// 具体处理者1:主管(可批准 1000 以内)
class Supervisor extends ApprovalHandler {
public Supervisor() {
super("主管");
}

@Override
public void handleRequest(int amount) {
if (amount <= 1000) {
System.out.println(name + " 批准了 " + amount + " 元的报销申请");
} else if (nextHandler != null) {
System.out.println(name + " 无权批准,转交上级处理");
nextHandler.handleRequest(amount);
}
}
}

// 具体处理者2:经理(可批准 5000 以内)
class Manager extends ApprovalHandler {
public Manager() {
super("经理");
}

@Override
public void handleRequest(int amount) {
if (amount <= 5000) {
System.out.println(name + " 批准了 " + amount + " 元的报销申请");
} else if (nextHandler != null) {
System.out.println(name + " 无权批准,转交上级处理");
nextHandler.handleRequest(amount);
}
}
}

// 具体处理者3:总监(可批准 10000 以内)
class Director extends ApprovalHandler {
public Director() {
super("总监");
}

@Override
public void handleRequest(int amount) {
if (amount <= 10000) {
System.out.println(name + " 批准了 " + amount + " 元的报销申请");
} else if (nextHandler != null) {
System.out.println(name + " 无权批准,转交上级处理");
nextHandler.handleRequest(amount);
}
}
}

// 具体处理者4:CEO(可批准任意金额)
class CEO extends ApprovalHandler {
public CEO() {
super("CEO");
}

@Override
public void handleRequest(int amount) {
System.out.println(name + " 批准了 " + amount + " 元的报销申请");
}
}

// 使用:构建责任链
ApprovalHandler supervisor = new Supervisor();
ApprovalHandler manager = new Manager();
ApprovalHandler director = new Director();
ApprovalHandler ceo = new CEO();

supervisor.setNextHandler(manager);
manager.setNextHandler(director);
director.setNextHandler(ceo);

// 测试不同金额的审批
supervisor.handleRequest(500); // 主管批准
supervisor.handleRequest(3000); // 经理批准
supervisor.handleRequest(8000); // 总监批准
supervisor.handleRequest(20000); // CEO批准

实际应用:

1
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
// Servlet 过滤器链
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// 前置处理
System.out.println("过滤器处理");

// 传递给下一个过滤器
chain.doFilter(request, response);

// 后置处理
}
}

// Spring Security 的过滤器链
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.build();
}
}

// MyBatis 的插件链(拦截器)
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 前置处理
Object result = invocation.proceed(); // 继续执行
// 后置处理
return result;
}
}

设计模式在实际项目中的应用

Spring 框架中的设计模式

  1. 单例模式: Spring Bean 默认是单例的
  2. 工厂模式: BeanFactory 和 ApplicationContext
  3. 代理模式: AOP 实现
  4. 模板方法模式: JdbcTemplate、RestTemplate
  5. 观察者模式: Spring Event 事件机制
  6. 适配器模式: HandlerAdapter
  7. 策略模式: Resource 接口的不同实现

MyBatis 中的设计模式

  1. 工厂模式: SqlSessionFactory
  2. 建造者模式: SqlSessionFactoryBuilder
  3. 代理模式: Mapper 接口的动态代理
  4. 模板方法模式: BaseExecutor
  5. 装饰器模式: Cache 的包装

JDK 中的设计模式

  1. 单例模式: Runtime.getRuntime()
  2. 工厂模式: Calendar.getInstance()
  3. 装饰器模式: IO 流
  4. 适配器模式: InputStreamReader
  5. 迭代器模式: Iterator
  6. 观察者模式: Observable 和 Observer
  7. 策略模式: Comparator