设计模式
GoF 23 种设计模式在 Java 中的经典实现。
设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
一、设计模式概述
1.1 什么是设计模式
设计模式描述了在软件设计过程中针对特定场景的、可重复使用的解决方案。1995 年,GoF(Gang of Four,四人组)出版了《Design Patterns: Elements of Reusable Object-Oriented Software》,定义了 23 种经典设计模式。
1.2 模式的分类
设计模式按目的分为三大类:
| 类别 | 关注点 | 包含模式 |
|---|---|---|
| 创建型模式 | 对象的创建过程 | 单例、工厂方法、抽象工厂、建造者、原型 |
| 结构型模式 | 类和对象的组合 | 代理、适配器、装饰器、外观、组合、桥接、享元 |
| 行为型模式 | 对象之间的通信 | 策略、模板方法、观察者、责任链、命令、状态、迭代器、访问者、中介者、备忘录、解释器 |
1.3 六大设计原则(SOLID + 最少知识原则)
在设计模式中,面向对象设计原则是基石。以下是六个核心原则:
| 缩写 | 原则名称 | 核心思想 |
|---|---|---|
| S | 单一职责原则(SRP) | 一个类只有一个引起它变化的原因 |
| O | 开闭原则(OCP) | 对扩展开放,对修改关闭 |
| L | 里氏替换原则(LSP) | 子类必须能替换父类 |
| I | 接口隔离原则(ISP) | 接口应该小而专,不强迫依赖不需要的方法 |
| D | 依赖倒置原则(DIP) | 面向接口编程,不依赖具体实现 |
| LoD | 最少知识原则(迪米特法则) | 一个对象应尽可能少地了解其他对象 |
单一职责原则(SRP)
// 反例:一个类负责多个职责
public class UserService {
public void saveUser(User user) { /* 数据持久化 */ }
public void sendEmail(User user) { /* 发送邮件 */ }
public void generateReport(User user) { /* 生成报表 */ }
}
// 正例:拆分职责
public class UserService {
public void saveUser(User user) { /* 数据持久化 */ }
}
public class EmailService {
public void sendEmail(User user) { /* 发送邮件 */ }
}
public class ReportService {
public void generateReport(User user) { /* 生成报表 */ }
}// 反例:一个类负责多个职责
public class UserService {
public void saveUser(User user) { /* 数据持久化 */ }
public void sendEmail(User user) { /* 发送邮件 */ }
public void generateReport(User user) { /* 生成报表 */ }
}
// 正例:拆分职责
public class UserService {
public void saveUser(User user) { /* 数据持久化 */ }
}
public class EmailService {
public void sendEmail(User user) { /* 发送邮件 */ }
}
public class ReportService {
public void generateReport(User user) { /* 生成报表 */ }
}开闭原则(OCP)
// 对扩展开放,对修改关闭
public interface Shape {
double area();
}
public class Rectangle implements Shape {
private double width, height;
public double area() { return width * height; }
}
public class Circle implements Shape {
private double radius;
public double area() { return Math.PI * radius * radius; }
}
// 新增三角形不需要修改现有代码,只需实现 Shape 接口// 对扩展开放,对修改关闭
public interface Shape {
double area();
}
public class Rectangle implements Shape {
private double width, height;
public double area() { return width * height; }
}
public class Circle implements Shape {
private double radius;
public double area() { return Math.PI * radius * radius; }
}
// 新增三角形不需要修改现有代码,只需实现 Shape 接口依赖倒置原则(DIP)
// 高层模块不依赖低层模块,二者都依赖抽象
public interface Database {
void save(Object obj);
}
public class MySQLDatabase implements Database {
public void save(Object obj) { /* MySQL 保存 */ }
}
public class UserService {
private Database database; // 依赖抽象,不依赖具体实现
public UserService(Database database) {
this.database = database;
}
}// 高层模块不依赖低层模块,二者都依赖抽象
public interface Database {
void save(Object obj);
}
public class MySQLDatabase implements Database {
public void save(Object obj) { /* MySQL 保存 */ }
}
public class UserService {
private Database database; // 依赖抽象,不依赖具体实现
public UserService(Database database) {
this.database = database;
}
}二、创建型模式(Creational Patterns)
创建型模式关注对象的创建机制,将对象的创建与使用分离,使系统在创建对象时更加灵活。
2.1 单例模式(Singleton Pattern)
定义:确保一个类只有一个实例,并提供一个全局访问点。
单例模式是 Java 中使用最广泛的设计模式之一,也是面试考查的重点。
2.1.1 饿汉式(Eager Initialization)
public class SingletonEager {
private static final SingletonEager INSTANCE = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}public class SingletonEager {
private static final SingletonEager INSTANCE = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}- 优点:线程安全,实现简单
- 缺点:类加载时就创建实例,可能造成资源浪费
2.1.2 懒汉式(Lazy Initialization)
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}- 优点:延迟加载,需要时才创建
- 缺点:synchronized 加在方法上,性能较差
2.1.3 DCL(双重检查锁,Double-Checked Locking)
public class SingletonDCL {
private static volatile SingletonDCL instance;
private SingletonDCL() {}
public static SingletonDCL getInstance() {
if (instance == null) { // 第一次检查
synchronized (SingletonDCL.class) {
if (instance == null) { // 第二次检查
instance = new SingletonDCL();
}
}
}
return instance;
}
}public class SingletonDCL {
private static volatile SingletonDCL instance;
private SingletonDCL() {}
public static SingletonDCL getInstance() {
if (instance == null) { // 第一次检查
synchronized (SingletonDCL.class) {
if (instance == null) { // 第二次检查
instance = new SingletonDCL();
}
}
}
return instance;
}
}- volatile 关键字:禁止指令重排序,保证可见性
- 双重检查:只在第一次创建时进入同步块,后续直接返回
2.1.4 静态内部类(Static Inner Class / Holder Pattern)
public class SingletonHolder {
private SingletonHolder() {}
private static class Holder {
private static final SingletonHolder INSTANCE = new SingletonHolder();
}
public static SingletonHolder getInstance() {
return Holder.INSTANCE;
}
}public class SingletonHolder {
private SingletonHolder() {}
private static class Holder {
private static final SingletonHolder INSTANCE = new SingletonHolder();
}
public static SingletonHolder getInstance() {
return Holder.INSTANCE;
}
}- 原理:JVM 在加载静态内部类时才会创建实例,既实现了延迟加载,又保证了线程安全
- 优点:最推荐的实现方式之一,性能高
2.1.5 枚举单例(Enum Singleton)
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
// 业务方法
}
}public enum SingletonEnum {
INSTANCE;
public void doSomething() {
// 业务方法
}
}- 优点:
- 线程安全,JVM 保证
- 天然防止反射破坏
- 天然防止序列化破坏
- 简洁
- 推荐:Effective Java 作者 Joshua Bloch 推荐的方式
2.1.6 防止反射和序列化破坏
防止反射破坏:
public class SingletonSafe {
private static final SingletonSafe INSTANCE = new SingletonSafe();
private SingletonSafe() {
// 防止反射调用
if (INSTANCE != null) {
throw new RuntimeException("不允许通过反射创建实例");
}
}
public static SingletonSafe getInstance() {
return INSTANCE;
}
}public class SingletonSafe {
private static final SingletonSafe INSTANCE = new SingletonSafe();
private SingletonSafe() {
// 防止反射调用
if (INSTANCE != null) {
throw new RuntimeException("不允许通过反射创建实例");
}
}
public static SingletonSafe getInstance() {
return INSTANCE;
}
}防止序列化破坏:
import java.io.Serializable;
public class SingletonSerializable implements Serializable {
private static final SingletonSerializable INSTANCE = new SingletonSerializable();
private SingletonSerializable() {}
public static SingletonSerializable getInstance() {
return INSTANCE;
}
// 实现 readResolve 方法,返回已有的实例
private Object readResolve() {
return INSTANCE;
}
}import java.io.Serializable;
public class SingletonSerializable implements Serializable {
private static final SingletonSerializable INSTANCE = new SingletonSerializable();
private SingletonSerializable() {}
public static SingletonSerializable getInstance() {
return INSTANCE;
}
// 实现 readResolve 方法,返回已有的实例
private Object readResolve() {
return INSTANCE;
}
}2.1.7 Spring Bean 中的单例
Spring 容器中 Bean 的默认作用域为 singleton,但 Spring 的单例与 GoF 的单例不同:
- Scope 为 singleton:每个 Spring IoC 容器中只有一个 Bean 实例
- 底层实现:Spring 通过容器级别的 Map 缓存来保证单例,而非通过类的静态属性
- 同一个类可以在 Spring 容器中被多次声明为不同的 Bean
@Component
@Scope("singleton") // 默认就是 singleton
public class MyService {
// Spring 容器中只有这个 Bean 的一个实例
}@Component
@Scope("singleton") // 默认就是 singleton
public class MyService {
// Spring 容器中只有这个 Bean 的一个实例
}2.2 工厂模式(Factory Pattern)
2.2.1 简单工厂(Simple Factory / 静态工厂)
public interface Product {
void use();
}
public class ConcreteProductA implements Product {
public void use() { System.out.println("Product A"); }
}
public class ConcreteProductB implements Product {
public void use() { System.out.println("Product B"); }
}
// 简单工厂
public class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A": return new ConcreteProductA();
case "B": return new ConcreteProductB();
default: throw new IllegalArgumentException("Unknown type: " + type);
}
}
}public interface Product {
void use();
}
public class ConcreteProductA implements Product {
public void use() { System.out.println("Product A"); }
}
public class ConcreteProductB implements Product {
public void use() { System.out.println("Product B"); }
}
// 简单工厂
public class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A": return new ConcreteProductA();
case "B": return new ConcreteProductB();
default: throw new IllegalArgumentException("Unknown type: " + type);
}
}
}注意:简单工厂不是 GoF 23 种设计模式之一,但很常用。
2.2.2 工厂方法(Factory Method)
// 抽象工厂
public interface Factory {
Product createProduct();
}
// 具体工厂 A
public class FactoryA implements Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂 B
public class FactoryB implements Factory {
public Product createProduct() {
return new ConcreteProductB();
}
}
// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();// 抽象工厂
public interface Factory {
Product createProduct();
}
// 具体工厂 A
public class FactoryA implements Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂 B
public class FactoryB implements Factory {
public Product createProduct() {
return new ConcreteProductB();
}
}
// 使用
Factory factory = new FactoryA();
Product product = factory.createProduct();- 适用场景:当一个类不知道它需要创建哪个具体类的对象时
- 优点:符合开闭原则,增加新产品无需修改现有工厂类
2.2.3 抽象工厂(Abstract Factory)
// 产品族:一个工厂可以生产多个产品
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
public ProductA createProductA() { return new ProductA1(); }
public ProductB createProductB() { return new ProductB1(); }
}
public class ConcreteFactory2 implements AbstractFactory {
public ProductA createProductA() { return new ProductA2(); }
public ProductB createProductB() { return new ProductB2(); }
}// 产品族:一个工厂可以生产多个产品
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
public ProductA createProductA() { return new ProductA1(); }
public ProductB createProductB() { return new ProductB1(); }
}
public class ConcreteFactory2 implements AbstractFactory {
public ProductA createProductA() { return new ProductA2(); }
public ProductB createProductB() { return new ProductB2(); }
}- 适用场景:系统需要创建一组相关或相互依赖的对象(产品族)
- 与工厂方法的区别:工厂方法针对单一产品等级结构,抽象工厂针对多个产品等级结构
2.2.4 Spring 中的工厂模式
Spring 的 BeanFactory 是工厂模式的经典体现:
// BeanFactory 是抽象工厂
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = factory.getBean("userService", UserService.class);// BeanFactory 是抽象工厂
BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = factory.getBean("userService", UserService.class);BeanFactory:顶层接口,定义了获取 Bean 的方法ApplicationContext:高级容器,扩展了 BeanFactoryFactoryBean:允许用户自定义创建 Bean 的逻辑
2.3 建造者模式(Builder Pattern)
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
public class Computer {
private String cpu;
private String ram;
private String storage;
private boolean hasBluetooth;
private boolean hasWifi;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.hasBluetooth = builder.hasBluetooth;
this.hasWifi = builder.hasWifi;
}
// 静态内部 Builder 类
public static class Builder {
private String cpu;
private String ram;
private String storage;
private boolean hasBluetooth;
private boolean hasWifi;
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 Builder bluetooth(boolean hasBluetooth) { this.hasBluetooth = hasBluetooth; return this; }
public Builder wifi(boolean hasWifi) { this.hasWifi = hasWifi; return this; }
public Computer build() {
return new Computer(this);
}
}
}
// 链式调用
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.ram("16GB")
.storage("512GB SSD")
.bluetooth(true)
.wifi(true)
.build();public class Computer {
private String cpu;
private String ram;
private String storage;
private boolean hasBluetooth;
private boolean hasWifi;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
this.hasBluetooth = builder.hasBluetooth;
this.hasWifi = builder.hasWifi;
}
// 静态内部 Builder 类
public static class Builder {
private String cpu;
private String ram;
private String storage;
private boolean hasBluetooth;
private boolean hasWifi;
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 Builder bluetooth(boolean hasBluetooth) { this.hasBluetooth = hasBluetooth; return this; }
public Builder wifi(boolean hasWifi) { this.hasWifi = hasWifi; return this; }
public Computer build() {
return new Computer(this);
}
}
}
// 链式调用
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.ram("16GB")
.storage("512GB SSD")
.bluetooth(true)
.wifi(true)
.build();Lombok @Builder 注解:
import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class User {
private String name;
private int age;
private String email;
private String phone;
}
// 使用
User user = User.builder()
.name("张三")
.age(25)
.email("zhangsan@example.com")
.build();import lombok.Builder;
import lombok.ToString;
@Builder
@ToString
public class User {
private String name;
private int age;
private String email;
private String phone;
}
// 使用
User user = User.builder()
.name("张三")
.age(25)
.email("zhangsan@example.com")
.build();- 适用场景:对象构造参数多且复杂,需要灵活的构建过程
- 优点:链式调用代码可读性好;将构建过程与表现分离
2.4 原型模式(Prototype Pattern)
定义:通过复制已有对象来创建新对象,而不是通过 new 创建。
public class Prototype implements Cloneable {
private String name;
private List<String> tags;
public Prototype(String name, List<String> tags) {
this.name = name;
this.tags = tags;
}
// 浅拷贝
@Override
protected Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
// 深拷贝
public Prototype deepClone() {
Prototype p = new Prototype(this.name, new ArrayList<>(this.tags));
return p;
}
}public class Prototype implements Cloneable {
private String name;
private List<String> tags;
public Prototype(String name, List<String> tags) {
this.name = name;
this.tags = tags;
}
// 浅拷贝
@Override
protected Prototype clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
// 深拷贝
public Prototype deepClone() {
Prototype p = new Prototype(this.name, new ArrayList<>(this.tags));
return p;
}
}浅拷贝 vs 深拷贝:
| 对比项 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 基本类型 | 复制值 | 复制值 |
| 引用类型 | 复制引用(指向同一对象) | 创建新对象 |
| 实现方式 | super.clone() | 序列化 / new / 手动复制 |
| 性能 | 高 | 较低 |
深拷贝的序列化方式:
public class DeepClonePrototype implements Serializable {
private String name;
private List<String> tags;
public DeepClonePrototype deepClone() {
try {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepClonePrototype) ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}public class DeepClonePrototype implements Serializable {
private String name;
private List<String> tags;
public DeepClonePrototype deepClone() {
try {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepClonePrototype) ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}- 适用场景:创建对象成本较大(如数据库查询),且对象之间差异不大
- Java 中:必须实现 Cloneable 接口(标记接口),重写 clone() 方法
三、结构型模式(Structural Patterns)
结构型模式关注类和对象的组合,通过继承或组合来构建更大的结构。
3.1 代理模式(Proxy Pattern)
定义:为其他对象提供一种代理以控制对这个对象的访问。代理模式是 AOP 的底层实现基础,也是面试重点。
3.1.1 静态代理
通过组合或继承实现,代理类在编译期就已经确定。
// 接口
public interface UserService {
void saveUser(User user);
}
// 目标类
public class UserServiceImpl implements UserService {
public void saveUser(User user) {
System.out.println("保存用户: " + user.getName());
}
}
// 静态代理类(组合方式)
public class UserServiceProxy implements UserService {
private UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
public void saveUser(User user) {
System.out.println("前置处理:权限检查");
target.saveUser(user);
System.out.println("后置处理:记录日志");
}
}// 接口
public interface UserService {
void saveUser(User user);
}
// 目标类
public class UserServiceImpl implements UserService {
public void saveUser(User user) {
System.out.println("保存用户: " + user.getName());
}
}
// 静态代理类(组合方式)
public class UserServiceProxy implements UserService {
private UserService target;
public UserServiceProxy(UserService target) {
this.target = target;
}
public void saveUser(User user) {
System.out.println("前置处理:权限检查");
target.saveUser(user);
System.out.println("后置处理:记录日志");
}
}- 优点:实现简单
- 缺点:每个目标类需要单独编写代理类,代理类数量膨胀
3.1.2 JDK 动态代理
在运行时动态创建代理对象,要求目标类必须实现接口。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyHandler implements InvocationHandler {
private Object target;
public JdkProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK 动态代理 - 前置处理");
Object result = method.invoke(target, args);
System.out.println("JDK 动态代理 - 后置处理");
return result;
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JdkProxyHandler(target)
);
}
}
// 使用
UserService proxy = JdkProxyHandler.createProxy(new UserServiceImpl());
proxy.saveUser(user);import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyHandler implements InvocationHandler {
private Object target;
public JdkProxyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK 动态代理 - 前置处理");
Object result = method.invoke(target, args);
System.out.println("JDK 动态代理 - 后置处理");
return result;
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JdkProxyHandler(target)
);
}
}
// 使用
UserService proxy = JdkProxyHandler.createProxy(new UserServiceImpl());
proxy.saveUser(user);核心 API:
java.lang.reflect.Proxy:创建代理类java.lang.reflect.InvocationHandler:调用处理器接口
3.1.3 CGLIB 动态代理
通过继承目标类创建子类作为代理,不需要接口。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyInterceptor implements MethodInterceptor {
private Object target;
public CglibProxyInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("CGLIB 动态代理 - 前置处理");
Object result = proxy.invoke(target, args); // 调用目标对象
System.out.println("CGLIB 动态代理 - 后置处理");
return result;
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibProxyInterceptor(target));
return (T) enhancer.create();
}
}
// 使用(不需要接口)
UserServiceImpl proxy = CglibProxyInterceptor.createProxy(new UserServiceImpl());
proxy.saveUser(user);import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyInterceptor implements MethodInterceptor {
private Object target;
public CglibProxyInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("CGLIB 动态代理 - 前置处理");
Object result = proxy.invoke(target, args); // 调用目标对象
System.out.println("CGLIB 动态代理 - 后置处理");
return result;
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibProxyInterceptor(target));
return (T) enhancer.create();
}
}
// 使用(不需要接口)
UserServiceImpl proxy = CglibProxyInterceptor.createProxy(new UserServiceImpl());
proxy.saveUser(user);核心 API:
net.sf.cglib.proxy.Enhancer:字节码增强器net.sf.cglib.proxy.MethodInterceptor:方法拦截器
3.1.4 JDK 动态代理 vs CGLIB 动态代理
| 对比项 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 原理 | 基于接口,生成实现类的代理 | 基于继承,生成子类 |
| 要求 | 目标类必须实现接口 | 目标类不能是 final 的 |
| 实现方式 | InvocationHandler + Proxy | MethodInterceptor + Enhancer |
| 性能 | 创建代理对象快,调用方法慢 | 创建代理对象慢,调用方法快 |
| 依赖 | JDK 自带 | 需要引入 cglib 依赖(Spring 已内置) |
3.1.5 Spring AOP 代理选择策略
// Spring AOP 底层自动判断使用哪种代理
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice() {
System.out.println("方法执行前");
}
}// Spring AOP 底层自动判断使用哪种代理
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice() {
System.out.println("方法执行前");
}
}Spring AOP 的代理选择逻辑:
- 目标类实现了接口:默认使用 JDK 动态代理
- 目标类没有实现接口:使用 CGLIB 动态代理
- 强制使用 CGLIB:配置
spring.aop.proxy-target-class=true - Spring Boot 2.0+ 默认使用 CGLIB 代理
3.2 适配器模式(Adapter Pattern)
定义:将一个类的接口转换成客户希望的另一个接口,使原来不兼容的类可以协同工作。
3.2.1 类适配器(基于继承)
// 目标接口
public interface Target {
void request();
}
// 被适配者
public class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 适配器(继承被适配者)
public class ClassAdapter extends Adaptee implements Target {
public void request() {
specificRequest(); // 调用被适配者的方法
}
}// 目标接口
public interface Target {
void request();
}
// 被适配者
public class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 适配器(继承被适配者)
public class ClassAdapter extends Adaptee implements Target {
public void request() {
specificRequest(); // 调用被适配者的方法
}
}3.2.2 对象适配器(基于组合)
// 适配器(持有被适配者的引用,推荐方式)
public class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}// 适配器(持有被适配者的引用,推荐方式)
public class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
public void request() {
adaptee.specificRequest();
}
}3.2.3 Spring MVC HandlerAdapter
Spring MVC 使用适配器模式来统一处理不同类型的控制器:
// HandlerAdapter 接口(适配器)
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
// SimpleControllerHandlerAdapter:适配实现了 Controller 接口的处理器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(...) {
return ((Controller) handler).handleRequest(request, response);
}
}
// HttpRequestHandlerAdapter:适配实现了 HttpRequestHandler 的处理器
public class HttpRequestHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
public ModelAndView handle(...) {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
}// HandlerAdapter 接口(适配器)
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
// SimpleControllerHandlerAdapter:适配实现了 Controller 接口的处理器
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
public ModelAndView handle(...) {
return ((Controller) handler).handleRequest(request, response);
}
}
// HttpRequestHandlerAdapter:适配实现了 HttpRequestHandler 的处理器
public class HttpRequestHandlerAdapter implements HandlerAdapter {
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
public ModelAndView handle(...) {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
}3.3 装饰器模式(Decorator Pattern)
定义:动态地给一个对象添加额外的职责,比继承更加灵活。
3.3.1 Java IO InputStream 体系
装饰器模式在 Java IO 中有着经典应用:
InputStream inputStream = new BufferedInputStream( // 装饰:提供缓冲功能
new DataInputStream( // 装饰:提供基本数据类型的读取
new FileInputStream("test.txt") // 被装饰者
)
);InputStream inputStream = new BufferedInputStream( // 装饰:提供缓冲功能
new DataInputStream( // 装饰:提供基本数据类型的读取
new FileInputStream("test.txt") // 被装饰者
)
);InputStream 体系中的角色:
| 角色 | 类名 | 说明 |
|---|---|---|
| 抽象组件 | InputStream | 顶级抽象类 |
| 具体组件 | FileInputStream | 被装饰的原始对象 |
| 抽象装饰器 | FilterInputStream | 装饰器基类 |
| 具体装饰器 | BufferedInputStream | 提供缓冲功能 |
| 具体装饰器 | DataInputStream | 提供基本数据类型读取 |
| 具体装饰器 | PushbackInputStream | 提供回退功能 |
3.3.2 自定义装饰器示例
// 抽象组件
public interface Coffee {
double cost();
String description();
}
// 具体组件
public class SimpleCoffee implements Coffee {
public double cost() { return 10.0; }
public String description() { return "普通咖啡"; }
}
// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
public double cost() { return coffee.cost(); }
public String description() { return coffee.description(); }
}
// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) { super(coffee); }
public double cost() { return coffee.cost() + 3.0; }
public String description() { return coffee.description() + " + 牛奶"; }
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) { super(coffee); }
public double cost() { return coffee.cost() + 1.0; }
public String description() { return coffee.description() + " + 糖"; }
}
// 使用
Coffee coffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
System.out.println(coffee.description() + " = " + coffee.cost() + "元");
// 输出:普通咖啡 + 牛奶 + 糖 = 14.0元// 抽象组件
public interface Coffee {
double cost();
String description();
}
// 具体组件
public class SimpleCoffee implements Coffee {
public double cost() { return 10.0; }
public String description() { return "普通咖啡"; }
}
// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
public double cost() { return coffee.cost(); }
public String description() { return coffee.description(); }
}
// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) { super(coffee); }
public double cost() { return coffee.cost() + 3.0; }
public String description() { return coffee.description() + " + 牛奶"; }
}
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) { super(coffee); }
public double cost() { return coffee.cost() + 1.0; }
public String description() { return coffee.description() + " + 糖"; }
}
// 使用
Coffee coffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
System.out.println(coffee.description() + " = " + coffee.cost() + "元");
// 输出:普通咖啡 + 牛奶 + 糖 = 14.0元3.3.3 装饰器 vs 继承
| 对比项 | 装饰器模式 | 继承 |
|---|---|---|
| 扩展方式 | 动态组合 | 静态编译 |
| 增减功能 | 灵活运行时增减 | 需创建新子类 |
| 类数量 | 避免类爆炸 | 功能组合多时产生大量子类 |
| 客户端透明 | 客户端无需感知装饰过程 | 客户端需知道具体子类 |
3.4 外观模式(Facade Pattern)
定义:为子系统中的一组接口提供一个统一的接口,定义一个高层接口让子系统更容易使用。
// 子系统类
public class CPU {
public void start() { System.out.println("CPU 启动"); }
}
public class Memory {
public void load() { System.out.println("内存加载"); }
}
public class HardDrive {
public void read() { System.out.println("硬盘读取"); }
}
// 外观类
public class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("计算机启动完成");
}
}
// 客户端调用
ComputerFacade computer = new ComputerFacade();
computer.start(); // 一个调用完成所有启动步骤// 子系统类
public class CPU {
public void start() { System.out.println("CPU 启动"); }
}
public class Memory {
public void load() { System.out.println("内存加载"); }
}
public class HardDrive {
public void read() { System.out.println("硬盘读取"); }
}
// 外观类
public class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void start() {
cpu.start();
memory.load();
hardDrive.read();
System.out.println("计算机启动完成");
}
}
// 客户端调用
ComputerFacade computer = new ComputerFacade();
computer.start(); // 一个调用完成所有启动步骤- 适用场景:为复杂子系统提供简化接口,分层系统中的 Service 层
- 优点:减少系统耦合、提高易用性
3.5 组合模式(Composite Pattern)
定义:将对象组合成树形结构以表示"部分-整体"的层次结构,使客户端对单个对象和组合对象的使用具有一致性。
// 抽象组件
public interface FileComponent {
void show();
long getSize();
}
// 叶子节点:文件
public class FileLeaf implements FileComponent {
private String name;
private long size;
public FileLeaf(String name, long size) {
this.name = name;
this.size = size;
}
public void show() { System.out.println("文件: " + name); }
public long getSize() { return size; }
}
// 组合节点:文件夹
public class FolderComposite implements FileComponent {
private String name;
private List<FileComponent> children = new ArrayList<>();
public FolderComposite(String name) { this.name = name; }
public void add(FileComponent component) { children.add(component); }
public void remove(FileComponent component) { children.remove(component); }
public void show() {
System.out.println("文件夹: " + name);
for (FileComponent child : children) {
child.show();
}
}
public long getSize() {
long total = 0;
for (FileComponent child : children) {
total += child.getSize();
}
return total;
}
}// 抽象组件
public interface FileComponent {
void show();
long getSize();
}
// 叶子节点:文件
public class FileLeaf implements FileComponent {
private String name;
private long size;
public FileLeaf(String name, long size) {
this.name = name;
this.size = size;
}
public void show() { System.out.println("文件: " + name); }
public long getSize() { return size; }
}
// 组合节点:文件夹
public class FolderComposite implements FileComponent {
private String name;
private List<FileComponent> children = new ArrayList<>();
public FolderComposite(String name) { this.name = name; }
public void add(FileComponent component) { children.add(component); }
public void remove(FileComponent component) { children.remove(component); }
public void show() {
System.out.println("文件夹: " + name);
for (FileComponent child : children) {
child.show();
}
}
public long getSize() {
long total = 0;
for (FileComponent child : children) {
total += child.getSize();
}
return total;
}
}- 适用场景:树形菜单、文件系统、组织架构等树形结构
- 透明方式 vs 安全方式:透明方式将管理方法放在抽象组件中,安全方式将管理方法放在组合节点中
3.6 桥接模式(Bridge Pattern)
定义:将抽象部分与实现部分分离,使它们可以独立地变化。
// 实现接口
public interface DrawAPI {
void drawCircle(int x, int y, int radius);
}
// 具体实现 A
public class RedDraw implements DrawAPI {
public void drawCircle(int x, int y, int radius) {
System.out.println("画红色圆,坐标(" + x + "," + y + "),半径" + radius);
}
}
// 具体实现 B
public class BlueDraw implements DrawAPI {
public void drawCircle(int x, int y, int radius) {
System.out.println("画蓝色圆,坐标(" + x + "," + y + "),半径" + radius);
}
}
// 抽象类
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
// 扩展抽象类
public class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x; this.y = y; this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(x, y, radius);
}
}// 实现接口
public interface DrawAPI {
void drawCircle(int x, int y, int radius);
}
// 具体实现 A
public class RedDraw implements DrawAPI {
public void drawCircle(int x, int y, int radius) {
System.out.println("画红色圆,坐标(" + x + "," + y + "),半径" + radius);
}
}
// 具体实现 B
public class BlueDraw implements DrawAPI {
public void drawCircle(int x, int y, int radius) {
System.out.println("画蓝色圆,坐标(" + x + "," + y + "),半径" + radius);
}
}
// 抽象类
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
// 扩展抽象类
public class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x; this.y = y; this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(x, y, radius);
}
}JDBC DriverManager 中的桥接模式:
// Driver 是桥接中的"实现"接口
// DriverManager 是桥接中的"抽象"
// 不同数据库驱动(MySQL、Oracle)是具体实现
// 客户端只需要面向 JDBC 接口编程
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db");
// 底层实际调用 MySQL 驱动或 Oracle 驱动// Driver 是桥接中的"实现"接口
// DriverManager 是桥接中的"抽象"
// 不同数据库驱动(MySQL、Oracle)是具体实现
// 客户端只需要面向 JDBC 接口编程
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db");
// 底层实际调用 MySQL 驱动或 Oracle 驱动3.7 享元模式(Flyweight Pattern)
定义:运用共享技术有效地支持大量细粒度的对象。
// 享元接口
public interface Flyweight {
void operate(String extrinsicState);
}
// 具体享元
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState; // 内部状态(可共享)
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operate(String extrinsicState) { // 外部状态(不可共享)
System.out.println("内部状态: " + intrinsicState + ", 外部状态: " + extrinsicState);
}
}
// 享元工厂
public class FlyweightFactory {
private static Map<String, Flyweight> pool = new HashMap<>();
public static Flyweight getFlyweight(String key) {
Flyweight flyweight = pool.get(key);
if (flyweight == null) {
flyweight = new ConcreteFlyweight(key);
pool.put(key, flyweight);
}
return flyweight;
}
}// 享元接口
public interface Flyweight {
void operate(String extrinsicState);
}
// 具体享元
public class ConcreteFlyweight implements Flyweight {
private String intrinsicState; // 内部状态(可共享)
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operate(String extrinsicState) { // 外部状态(不可共享)
System.out.println("内部状态: " + intrinsicState + ", 外部状态: " + extrinsicState);
}
}
// 享元工厂
public class FlyweightFactory {
private static Map<String, Flyweight> pool = new HashMap<>();
public static Flyweight getFlyweight(String key) {
Flyweight flyweight = pool.get(key);
if (flyweight == null) {
flyweight = new ConcreteFlyweight(key);
pool.put(key, flyweight);
}
return flyweight;
}
}Java 中的享元模式应用:
String 常量池:相同的字符串字面量共享同一个对象
javaString s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // trueString s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // trueInteger 缓存:默认缓存 -128 到 127 的 Integer 对象
javaInteger i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); // true Integer i3 = 200; Integer i4 = 200; System.out.println(i3 == i4); // false(超出缓存范围)Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); // true Integer i3 = 200; Integer i4 = 200; System.out.println(i3 == i4); // false(超出缓存范围)
四、行为型模式(Behavioral Patterns)
行为型模式关注对象之间的通信和职责分配。
4.1 策略模式(Strategy Pattern)
定义:定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。
// 策略接口
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略 A
public class AlipayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("支付宝支付:" + amount + "元");
}
}
// 具体策略 B
public class WechatPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("微信支付:" + amount + "元");
}
}
// 具体策略 C
public class CreditCardStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("信用卡支付:" + amount + "元");
}
}
// 上下文
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
strategy.pay(amount);
}
}
// 使用
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0);
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0);// 策略接口
public interface PaymentStrategy {
void pay(double amount);
}
// 具体策略 A
public class AlipayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("支付宝支付:" + amount + "元");
}
}
// 具体策略 B
public class WechatPayStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("微信支付:" + amount + "元");
}
}
// 具体策略 C
public class CreditCardStrategy implements PaymentStrategy {
public void pay(double amount) {
System.out.println("信用卡支付:" + amount + "元");
}
}
// 上下文
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
strategy.pay(amount);
}
}
// 使用
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100.0);
context.setStrategy(new WechatPayStrategy());
context.executePayment(200.0);Spring 中的策略模式注入:
// Spring 通过 @Autowired + Map 自动注入所有策略
@Component
public class PaymentService {
@Autowired
private Map<String, PaymentStrategy> strategyMap; // key=bean名称, value=策略实例
public void pay(String channel, double amount) {
PaymentStrategy strategy = strategyMap.get(channel + "PayStrategy");
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付渠道: " + channel);
}
strategy.pay(amount);
}
}// Spring 通过 @Autowired + Map 自动注入所有策略
@Component
public class PaymentService {
@Autowired
private Map<String, PaymentStrategy> strategyMap; // key=bean名称, value=策略实例
public void pay(String channel, double amount) {
PaymentStrategy strategy = strategyMap.get(channel + "PayStrategy");
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付渠道: " + channel);
}
strategy.pay(amount);
}
}- 适用场景:系统有多种相似的算法,需要动态切换
4.2 模板方法模式(Template Method Pattern)
定义:定义一个操作中的算法骨架,将一些步骤延迟到子类中实现。
// 抽象类定义骨架
public abstract class AbstractCooking {
// 模板方法(定义为 final,防止子类修改骨架)
public final void cook() {
prepareIngredients();
heatOil();
fry();
addSeasoning();
serve();
}
// 具体步骤(通用实现)
private void heatOil() { System.out.println("热油"); }
private void serve() { System.out.println("装盘上菜"); }
// 抽象步骤(子类实现)
protected abstract void prepareIngredients();
protected abstract void fry();
protected abstract void addSeasoning();
// 钩子方法(可选覆盖)
protected boolean needCutting() { return true; }
}
// 具体实现 A
public class TomatoEggCooking extends AbstractCooking {
protected void prepareIngredients() {
System.out.println("准备番茄和鸡蛋");
}
protected void fry() {
System.out.println("先炒鸡蛋,再炒番茄");
}
protected void addSeasoning() {
System.out.println("加盐和糖");
}
}
// 具体实现 B
public class MapoTofuCooking extends AbstractCooking {
protected void prepareIngredients() {
System.out.println("准备豆腐和肉末");
}
protected void fry() {
System.out.println("炒肉末,加豆瓣酱");
}
protected void addSeasoning() {
System.out.println("加花椒粉和淀粉水");
}
}// 抽象类定义骨架
public abstract class AbstractCooking {
// 模板方法(定义为 final,防止子类修改骨架)
public final void cook() {
prepareIngredients();
heatOil();
fry();
addSeasoning();
serve();
}
// 具体步骤(通用实现)
private void heatOil() { System.out.println("热油"); }
private void serve() { System.out.println("装盘上菜"); }
// 抽象步骤(子类实现)
protected abstract void prepareIngredients();
protected abstract void fry();
protected abstract void addSeasoning();
// 钩子方法(可选覆盖)
protected boolean needCutting() { return true; }
}
// 具体实现 A
public class TomatoEggCooking extends AbstractCooking {
protected void prepareIngredients() {
System.out.println("准备番茄和鸡蛋");
}
protected void fry() {
System.out.println("先炒鸡蛋,再炒番茄");
}
protected void addSeasoning() {
System.out.println("加盐和糖");
}
}
// 具体实现 B
public class MapoTofuCooking extends AbstractCooking {
protected void prepareIngredients() {
System.out.println("准备豆腐和肉末");
}
protected void fry() {
System.out.println("炒肉末,加豆瓣酱");
}
protected void addSeasoning() {
System.out.println("加花椒粉和淀粉水");
}
}Spring 中的模板方法:
// JdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<User> users = jdbcTemplate.query(
"SELECT * FROM users",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);// JdbcTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
List<User> users = jdbcTemplate.query(
"SELECT * FROM users",
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))
);
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);JdbcTemplate 内部使用模板方法模式:固定的流程(获取连接、创建语句、执行查询、处理结果集、关闭资源)由模板定义,其中的回调方法(如 RowMapper)由客户端实现。
4.3 观察者模式(Observer Pattern)
定义:定义对象间一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动更新。
发布-订阅模型是观察者模式的典型应用。
import java.util.ArrayList;
import java.util.List;
// 观察者接口
public interface Observer {
void update(String message);
}
// 具体观察者
public class UserObserver implements Observer {
private String name;
public UserObserver(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
// 被观察者(主题)
public class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void setState(String state) {
this.state = state;
notifyAllObservers();
}
private void notifyAllObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 使用
Subject subject = new Subject();
subject.attach(new UserObserver("张三"));
subject.attach(new UserObserver("李四"));
subject.setState("有新文章发布了!");import java.util.ArrayList;
import java.util.List;
// 观察者接口
public interface Observer {
void update(String message);
}
// 具体观察者
public class UserObserver implements Observer {
private String name;
public UserObserver(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
// 被观察者(主题)
public class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void setState(String state) {
this.state = state;
notifyAllObservers();
}
private void notifyAllObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 使用
Subject subject = new Subject();
subject.attach(new UserObserver("张三"));
subject.attach(new UserObserver("李四"));
subject.setState("有新文章发布了!");Spring 中的观察者模式:
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private Long orderId;
public OrderCreatedEvent(Object source, Long orderId) {
super(source);
this.orderId = orderId;
}
public Long getOrderId() { return orderId; }
}
// 2. 发布事件
@Component
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 创建订单逻辑...
publisher.publishEvent(new OrderCreatedEvent(this, order.getId()));
}
}
// 3. 监听事件(方式一:实现接口)
@Component
public class EmailListener implements ApplicationListener<OrderCreatedEvent> {
public void onApplicationEvent(OrderCreatedEvent event) {
System.out.println("发送订单创建邮件,订单ID: " + event.getOrderId());
}
}
// 4. 监听事件(方式二:注解,更常用)
@Component
public class SmsListener {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("发送订单创建短信,订单ID: " + event.getOrderId());
}
}
// 5. 异步监听(需要 @EnableAsync)
@Component
public class AsyncListener {
@Async
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// 异步处理,不影响主流程
System.out.println("异步处理订单: " + event.getOrderId());
}
}// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private Long orderId;
public OrderCreatedEvent(Object source, Long orderId) {
super(source);
this.orderId = orderId;
}
public Long getOrderId() { return orderId; }
}
// 2. 发布事件
@Component
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 创建订单逻辑...
publisher.publishEvent(new OrderCreatedEvent(this, order.getId()));
}
}
// 3. 监听事件(方式一:实现接口)
@Component
public class EmailListener implements ApplicationListener<OrderCreatedEvent> {
public void onApplicationEvent(OrderCreatedEvent event) {
System.out.println("发送订单创建邮件,订单ID: " + event.getOrderId());
}
}
// 4. 监听事件(方式二:注解,更常用)
@Component
public class SmsListener {
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("发送订单创建短信,订单ID: " + event.getOrderId());
}
}
// 5. 异步监听(需要 @EnableAsync)
@Component
public class AsyncListener {
@Async
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
// 异步处理,不影响主流程
System.out.println("异步处理订单: " + event.getOrderId());
}
}4.4 责任链模式(Chain of Responsibility Pattern)
定义:使多个对象都有机会处理请求,将这些对象连成一条链,并沿着这条链传递请求直到有对象处理它。
// 抽象处理器
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int level);
}
// 具体处理器 A
public class Level1Handler extends Handler {
public void handleRequest(int level) {
if (level <= 1) {
System.out.println("Level1 处理了请求");
} else if (next != null) {
next.handleRequest(level);
}
}
}
// 具体处理器 B
public class Level2Handler extends Handler {
public void handleRequest(int level) {
if (level <= 2) {
System.out.println("Level2 处理了请求");
} else if (next != null) {
next.handleRequest(level);
}
}
}
// 具体处理器 C
public class Level3Handler extends Handler {
public void handleRequest(int level) {
if (level <= 3) {
System.out.println("Level3 处理了请求");
} else {
System.out.println("无人能处理该请求");
}
}
}
// 使用
Handler h1 = new Level1Handler();
Handler h2 = new Level2Handler();
Handler h3 = new Level3Handler();
h1.setNext(h2);
h2.setNext(h3);
h1.handleRequest(2); // Level2 处理了请求// 抽象处理器
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int level);
}
// 具体处理器 A
public class Level1Handler extends Handler {
public void handleRequest(int level) {
if (level <= 1) {
System.out.println("Level1 处理了请求");
} else if (next != null) {
next.handleRequest(level);
}
}
}
// 具体处理器 B
public class Level2Handler extends Handler {
public void handleRequest(int level) {
if (level <= 2) {
System.out.println("Level2 处理了请求");
} else if (next != null) {
next.handleRequest(level);
}
}
}
// 具体处理器 C
public class Level3Handler extends Handler {
public void handleRequest(int level) {
if (level <= 3) {
System.out.println("Level3 处理了请求");
} else {
System.out.println("无人能处理该请求");
}
}
}
// 使用
Handler h1 = new Level1Handler();
Handler h2 = new Level2Handler();
Handler h3 = new Level3Handler();
h1.setNext(h2);
h2.setNext(h3);
h1.handleRequest(2); // Level2 处理了请求实际应用:
| 框架 | 责任链实现 |
|---|---|
| Servlet Filter | FilterChain 串联多个 Filter |
| Spring Interceptor | HandlerExecutionChain 串联多个 HandlerInterceptor |
| Netty Pipeline | ChannelPipeline 中的 ChannelHandler 链 |
| Spring Security | FilterChainProxy 管理安全过滤器链 |
| MyBatis 插件 | InterceptorChain 拦截器链 |
Servlet Filter 示例:
@WebFilter("/*")
public class LogFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
System.out.println("日志过滤前");
chain.doFilter(request, response); // 传递给下一个 Filter
System.out.println("日志过滤后");
}
}@WebFilter("/*")
public class LogFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
System.out.println("日志过滤前");
chain.doFilter(request, response); // 传递给下一个 Filter
System.out.println("日志过滤后");
}
}4.5 命令模式(Command Pattern)
定义:将请求封装为一个对象,从而可以用不同的请求对客户进行参数化。
// 命令接口
public interface Command {
void execute();
void undo();
}
// 具体命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
public void execute() { light.on(); }
public void undo() { light.off(); }
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) { this.light = light; }
public void execute() { light.off(); }
public void undo() { light.on(); }
}
// 接收者
public class Light {
public void on() { System.out.println("开灯"); }
public void off() { System.out.println("关灯"); }
}
// 调用者
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}// 命令接口
public interface Command {
void execute();
void undo();
}
// 具体命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
public void execute() { light.on(); }
public void undo() { light.off(); }
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) { this.light = light; }
public void execute() { light.off(); }
public void undo() { light.on(); }
}
// 接收者
public class Light {
public void on() { System.out.println("开灯"); }
public void off() { System.out.println("关灯"); }
}
// 调用者
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}Java 中的命令模式:
// Runnable 接口就是一个命令
Thread thread = new Thread(() -> System.out.println("执行任务"));
thread.start();
// 线程池的任务队列
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> System.out.println("任务执行")); // 提交 Command// Runnable 接口就是一个命令
Thread thread = new Thread(() -> System.out.println("执行任务"));
thread.start();
// 线程池的任务队列
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> System.out.println("任务执行")); // 提交 Command4.6 状态模式(State Pattern)
定义:允许一个对象在其内部状态改变时改变它的行为。
// 状态接口
public interface State {
void doAction(Context context);
}
// 具体状态 A
public class StartState implements State {
public void doAction(Context context) {
System.out.println("启动状态");
context.setState(this);
}
public String toString() { return "Start"; }
}
// 具体状态 B
public class StopState implements State {
public void doAction(Context context) {
System.out.println("停止状态");
context.setState(this);
}
public String toString() { return "Stop"; }
}
// 运行状态
public class RunningState implements State {
public void doAction(Context context) {
System.out.println("运行状态");
context.setState(this);
}
public String toString() { return "Running"; }
}
// 上下文
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
}// 状态接口
public interface State {
void doAction(Context context);
}
// 具体状态 A
public class StartState implements State {
public void doAction(Context context) {
System.out.println("启动状态");
context.setState(this);
}
public String toString() { return "Start"; }
}
// 具体状态 B
public class StopState implements State {
public void doAction(Context context) {
System.out.println("停止状态");
context.setState(this);
}
public String toString() { return "Stop"; }
}
// 运行状态
public class RunningState implements State {
public void doAction(Context context) {
System.out.println("运行状态");
context.setState(this);
}
public String toString() { return "Running"; }
}
// 上下文
public class Context {
private State state;
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
}- 与策略模式的区别:状态模式中状态之间可以转换,策略模式中策略由客户端选择和切换
- 适用场景:订单状态流转、流程审批等状态机场景
4.7 迭代器模式(Iterator Pattern)
定义:提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。
Java 集合框架中的迭代器模式:
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 增强 for 循环本质就是使用迭代器
for (String s : list) {
System.out.println(s);
}List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 增强 for 循环本质就是使用迭代器
for (String s : list) {
System.out.println(s);
}自定义迭代器:
public interface MyIterator<E> {
boolean hasNext();
E next();
}
public class MyList<E> implements Iterable<E> {
private E[] elements;
private int size;
public MyIterator<E> iterator() {
return new MyIterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < size;
}
public E next() {
return elements[index++];
}
};
}
}public interface MyIterator<E> {
boolean hasNext();
E next();
}
public class MyList<E> implements Iterable<E> {
private E[] elements;
private int size;
public MyIterator<E> iterator() {
return new MyIterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < size;
}
public E next() {
return elements[index++];
}
};
}
}4.8 访问者模式(Visitor Pattern)
定义:表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素类的前提下定义作用于这些元素的新操作。
// 访问者接口
public interface Visitor {
void visit(File file);
void visit(Directory directory);
}
// 具体访问者:打印访问者
public class PrintVisitor implements Visitor {
public void visit(File file) {
System.out.println("文件: " + file.getName());
}
public void visit(Directory dir) {
System.out.println("目录: " + dir.getName());
}
}
// 元素接口
public interface Element {
void accept(Visitor visitor);
}
// 具体元素 A
public class File implements Element {
private String name;
public File(String name) { this.name = name; }
public String getName() { return name; }
public void accept(Visitor visitor) { visitor.visit(this); }
}
// 具体元素 B
public class Directory implements Element {
private String name;
public Directory(String name) { this.name = name; }
public String getName() { return name; }
public void accept(Visitor visitor) { visitor.visit(this); }
}// 访问者接口
public interface Visitor {
void visit(File file);
void visit(Directory directory);
}
// 具体访问者:打印访问者
public class PrintVisitor implements Visitor {
public void visit(File file) {
System.out.println("文件: " + file.getName());
}
public void visit(Directory dir) {
System.out.println("目录: " + dir.getName());
}
}
// 元素接口
public interface Element {
void accept(Visitor visitor);
}
// 具体元素 A
public class File implements Element {
private String name;
public File(String name) { this.name = name; }
public String getName() { return name; }
public void accept(Visitor visitor) { visitor.visit(this); }
}
// 具体元素 B
public class Directory implements Element {
private String name;
public Directory(String name) { this.name = name; }
public String getName() { return name; }
public void accept(Visitor visitor) { visitor.visit(this); }
}Java NIO FileVisitor:
Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("文件: " + file.getFileName());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("目录: " + dir.getFileName());
return FileVisitResult.CONTINUE;
}
});Files.walkFileTree(Paths.get("."), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println("文件: " + file.getFileName());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
System.out.println("目录: " + dir.getFileName());
return FileVisitResult.CONTINUE;
}
});4.9 中介者模式(Mediator Pattern)
定义:用一个中介对象来封装一系列对象的交互,使各对象不需要显式地相互引用。
// 中介者接口
public interface Mediator {
void send(String message, Colleague colleague);
}
// 具体中介者
public class ChatRoom implements Mediator {
public void send(String message, Colleague colleague) {
System.out.println(colleague.getName() + " 发送消息: " + message);
}
}
// 同事类
public abstract class Colleague {
protected Mediator mediator;
protected String name;
public Colleague(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public String getName() { return name; }
public abstract void send(String message);
public abstract void receive(String message);
}
// 具体同事
public class User extends Colleague {
public User(Mediator mediator, String name) {
super(mediator, name);
}
public void send(String message) {
mediator.send(message, this);
}
public void receive(String message) {
System.out.println(name + " 收到: " + message);
}
}// 中介者接口
public interface Mediator {
void send(String message, Colleague colleague);
}
// 具体中介者
public class ChatRoom implements Mediator {
public void send(String message, Colleague colleague) {
System.out.println(colleague.getName() + " 发送消息: " + message);
}
}
// 同事类
public abstract class Colleague {
protected Mediator mediator;
protected String name;
public Colleague(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public String getName() { return name; }
public abstract void send(String message);
public abstract void receive(String message);
}
// 具体同事
public class User extends Colleague {
public User(Mediator mediator, String name) {
super(mediator, name);
}
public void send(String message) {
mediator.send(message, this);
}
public void receive(String message) {
System.out.println(name + " 收到: " + message);
}
}MVC 中的中介者:Controller 充当 View 和 Model 之间的中介者,协调视图和数据模型的交互。
4.10 备忘录模式(Memento Pattern)
定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复。
// 备忘录
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 原发器
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("设置状态: " + state);
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void restoreStateFromMemento(Memento memento) {
state = memento.getState();
System.out.println("恢复状态: " + state);
}
}
// 管理者
public class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}// 备忘录
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 原发器
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("设置状态: " + state);
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void restoreStateFromMemento(Memento memento) {
state = memento.getState();
System.out.println("恢复状态: " + state);
}
}
// 管理者
public class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}Java 中的备忘录模式:对象序列化(Serializable)是备忘录模式的一种体现,将对象状态保存到字节流中,可以随时恢复。
4.11 解释器模式(Interpreter Pattern)
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器来解释语言中的句子。
// 抽象表达式
public interface Expression {
int interpret();
}
// 终结符表达式:数字
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) { this.number = number; }
public int interpret() { return number; }
}
// 非终结符表达式:加法
public class AddExpression implements Expression {
private Expression left, right;
public AddExpression(Expression left, Expression right) {
this.left = left; this.right = right;
}
public int interpret() { return left.interpret() + right.interpret(); }
}
// 非终结符表达式:减法
public class SubtractExpression implements Expression {
private Expression left, right;
public SubtractExpression(Expression left, Expression right) {
this.left = left; this.right = right;
}
public int interpret() { return left.interpret() - right.interpret(); }
}
// 使用
// 表达式: 10 + 20 - 5
Expression result = new SubtractExpression(
new AddExpression(new NumberExpression(10), new NumberExpression(20)),
new NumberExpression(5)
);
System.out.println(result.interpret()); // 25// 抽象表达式
public interface Expression {
int interpret();
}
// 终结符表达式:数字
public class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) { this.number = number; }
public int interpret() { return number; }
}
// 非终结符表达式:加法
public class AddExpression implements Expression {
private Expression left, right;
public AddExpression(Expression left, Expression right) {
this.left = left; this.right = right;
}
public int interpret() { return left.interpret() + right.interpret(); }
}
// 非终结符表达式:减法
public class SubtractExpression implements Expression {
private Expression left, right;
public SubtractExpression(Expression left, Expression right) {
this.left = left; this.right = right;
}
public int interpret() { return left.interpret() - right.interpret(); }
}
// 使用
// 表达式: 10 + 20 - 5
Expression result = new SubtractExpression(
new AddExpression(new NumberExpression(10), new NumberExpression(20)),
new NumberExpression(5)
);
System.out.println(result.interpret()); // 25- 适用场景:正则表达式解析、SQL 解析、模板引擎
- 使用频率:较低,在特定领域(DSL、表达式解析)中使用
五、设计模式在 Spring 中的应用汇总
Spring 框架充分运用了各种设计模式,下表总结了主要的应用场景:
| 设计模式 | Spring 中的应用 |
|---|---|
| 工厂模式 | BeanFactory、ApplicationContext、FactoryBean |
| 单例模式 | Bean 的默认作用域 singleton,容器级单例 |
| 代理模式 | AOP 底层实现(JDK 动态代理 / CGLIB 代理) |
| 模板方法模式 | JdbcTemplate、RestTemplate、JmsTemplate、TransactionTemplate |
| 观察者模式 | ApplicationListener、@EventListener、ApplicationEventPublisher |
| 责任链模式 | HandlerInterceptor 拦截器链、Filter 过滤器链 |
| 适配器模式 | HandlerAdapter(适配不同 Controller 类型)、AdvisorAdapter |
| 策略模式 | Resource 接口的不同实现、AuthenticationProvider |
| 装饰器模式 | HttpServletRequestWrapper、HttpServletResponseWrapper、TransactionAwareCacheDecorator |
| 外观模式 | JdbcUtils、TransactionSynchronizationManager |
| 建造者模式 | UriComponentsBuilder、MockMvcBuilders、SecurityFilterChainBuilder |
| 原型模式 | Bean 作用域 prototype 每次获取都创建新实例 |
| 桥接模式 | ViewResolver 的抽象与实现分离 |
| 命令模式 | PlatformTransactionManager(将事务操作封装为命令) |
| 迭代器模式 | CompositeIterator 遍历组合对象 |
| 中介者模式 | Controller 作为 View 和 Model 的中介者(MVC) |
| 享元模式 | 连接池、Bean 缓存中复用对象 |
IoC 容器中的工厂 + 单例
// IoC 容器本质:工厂模式 + 单例模式
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 工厂模式:getBean 创建或获取对象
UserService userService = context.getBean(UserService.class);
// 单例模式:默认每个 Bean 在一个容器中只有一个实例
UserService s1 = context.getBean(UserService.class);
UserService s2 = context.getBean(UserService.class);
System.out.println(s1 == s2); // true// IoC 容器本质:工厂模式 + 单例模式
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 工厂模式:getBean 创建或获取对象
UserService userService = context.getBean(UserService.class);
// 单例模式:默认每个 Bean 在一个容器中只有一个实例
UserService s1 = context.getBean(UserService.class);
UserService s2 = context.getBean(UserService.class);
System.out.println(s1 == s2); // trueAOP 中的代理模式
@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前: " + joinPoint.getSignature());
Object result = joinPoint.proceed();
System.out.println("方法执行后: " + joinPoint.getSignature());
return result;
}
}@Aspect
@Component
public class LoggingAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("方法执行前: " + joinPoint.getSignature());
Object result = joinPoint.proceed();
System.out.println("方法执行后: " + joinPoint.getSignature());
return result;
}
}Spring AOP 在运行时为目标对象创建代理对象,在调用目标方法时插入切面逻辑。
Template 中的模板方法模式
// JdbcTemplate 固定了数据库操作的骨架
jdbcTemplate.execute("CREATE TABLE users (id INT, name VARCHAR(20))");
// 只需要提供 SQL 语句和处理结果的回调
List<User> users = jdbcTemplate.query(
"SELECT * FROM users WHERE age > ?",
new Object[]{18},
(rs, rowNum) -> new User(rs.getInt("id"), rs.getString("name"))
);// JdbcTemplate 固定了数据库操作的骨架
jdbcTemplate.execute("CREATE TABLE users (id INT, name VARCHAR(20))");
// 只需要提供 SQL 语句和处理结果的回调
List<User> users = jdbcTemplate.query(
"SELECT * FROM users WHERE age > ?",
new Object[]{18},
(rs, rowNum) -> new User(rs.getInt("id"), rs.getString("name"))
);Listener 中的观察者模式
// Spring 事件驱动机制是观察者模式的进阶实现
// 支持同步/异步、泛型事件、条件监听(@EventListener(condition = "..."))
// 事务绑定事件(@TransactionalEventListener)// Spring 事件驱动机制是观察者模式的进阶实现
// 支持同步/异步、泛型事件、条件监听(@EventListener(condition = "..."))
// 事务绑定事件(@TransactionalEventListener)Filter 中的责任链模式
// Spring Security 基于责任链模式构建安全过滤链
// 每个过滤器负责一项安全检查:认证、授权、CSRF、CORS 等
// 请求在过滤链中依次通过各过滤器
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}// Spring Security 基于责任链模式构建安全过滤链
// 每个过滤器负责一项安全检查:认证、授权、CSRF、CORS 等
// 请求在过滤链中依次通过各过滤器
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}Adapter 中的适配器模式
// Spring MVC 通过 HandlerAdapter 适配不同类型的处理器
// - SimpleControllerHandlerAdapter:适配 Controller 接口
// - HttpRequestHandlerAdapter:适配 HttpRequestHandler
// - AnnotationMethodHandlerAdapter:适配 @RequestMapping 方法(最常用)
// - SimpleServletHandlerAdapter:适配 Servlet
@RestController
public class UserController {
@GetMapping("/users")
public List<User> listUsers() {
// 处理器方法的参数和返回值由 HandlerAdapter 适配
return userService.findAll();
}
}// Spring MVC 通过 HandlerAdapter 适配不同类型的处理器
// - SimpleControllerHandlerAdapter:适配 Controller 接口
// - HttpRequestHandlerAdapter:适配 HttpRequestHandler
// - AnnotationMethodHandlerAdapter:适配 @RequestMapping 方法(最常用)
// - SimpleServletHandlerAdapter:适配 Servlet
@RestController
public class UserController {
@GetMapping("/users")
public List<User> listUsers() {
// 处理器方法的参数和返回值由 HandlerAdapter 适配
return userService.findAll();
}
}六、总结
6.1 设计模式选择指南
| 需求场景 | 推荐模式 |
|---|---|
| 需要全局唯一实例 | 单例模式 |
| 需要灵活创建对象 | 工厂方法 / 抽象工厂 |
| 对象构建过程复杂 | 建造者模式 |
| 需要大量相似对象 | 原型模式(克隆) |
| 需要控制对象访问 | 代理模式 |
| 接口不兼容需要转换 | 适配器模式 |
| 需要动态添加功能 | 装饰器模式 |
| 简化复杂子系统访问 | 外观模式 |
| 处理树形层次结构 | 组合模式 |
| 抽象与实现需要独立变化 | 桥接模式 |
| 共享大量细粒度对象 | 享元模式 |
| 算法需要动态切换 | 策略模式 |
| 算法骨架固定、步骤可变 | 模板方法模式 |
| 一对多依赖通知 | 观察者模式 |
| 请求需要多级处理 | 责任链模式 |
| 请求需要排队/撤销 | 命令模式 |
| 对象行为依赖其状态 | 状态模式 |
| 需统一遍历集合元素 | 迭代器模式 |
| 需在不改元素类的前提下增加操作 | 访问者模式 |
| 多对象交互需解耦 | 中介者模式 |
| 需要保存和恢复对象状态 | 备忘录模式 |
| 需要解释自定义语言 | 解释器模式 |
6.2 核心要点
- 设计原则优先于设计模式:不要为了用模式而用模式,遵循 SOLID 原则往往比套用模式更重要
- 组合优于继承:大多数设计模式都强调使用组合而非继承来复用代码
- 面向接口编程:将抽象与实现分离,降低耦合
- 开闭原则是核心:对扩展开放、对修改关闭是所有设计模式的共同追求
- 模式是工具不是教条:根据实际场景灵活应用,可以变体、组合使用多种模式
6.3 常见面试题
- 单例模式的几种写法及优缺点?如何防止反射和序列化破坏?
- JDK 动态代理与 CGLIB 动态代理的区别?Spring AOP 如何选择?
- 简单工厂、工厂方法、抽象工厂的区别与联系?
- 策略模式与状态模式的区别?
- 装饰器模式与代理模式的区别?(装饰器侧重功能增强,代理侧重访问控制)
- 适配器模式与装饰器模式的区别?(适配器用于接口转换,装饰器用于功能扩展)
- Spring 中用到了哪些设计模式?请举例说明。
- 如何实现一个线程安全的懒加载单例?(DCL + volatile,或静态内部类,或枚举)
- 模板方法模式与策略模式的区别?(模板方法强调算法骨架固定,策略强调算法可替换)
- 观察者模式中推模型与拉模型的区别?
Cao Note