设计模式基础
约 1147 字大约 4 分钟
布欧-Lewyon
2026-05-16
设计模式不是代码模板,而是解决特定问题的思路。GoF(Gang of Four)将 23 种经典模式分为三类:创建型、结构型、行为型。本节以 Java 示例讲解几个最常用且与日常开发紧密相关的模式。
设计原则(SOLID 简版)
| 原则 | 含义 | 反例 |
|---|---|---|
| 单一职责(S) | 一个类只做一件事 | 一个类既处理订单又发送邮件 |
| 开闭原则(O) | 对扩展开放,对修改关闭 | 每加一个功能就要修改原有类 |
| 依赖倒置(D) | 面向接口编程,不面向实现 | new MysqlUserDao() 硬编码具体实现 |
以下模式都体现了这些原则。
单例模式(Singleton)
确保一个类只有一个实例,并提供全局访问点。Spring 中的 Bean 默认为单例。
饿汉式(线程安全,类加载时创建)
public class ConfigManager {
private static final ConfigManager INSTANCE = new ConfigManager();
private Properties config = new Properties();
private ConfigManager() {
// 加载配置文件
}
public static ConfigManager getInstance() {
return INSTANCE;
}
public String get(String key) {
return config.getProperty(key);
}
}懒汉式(延迟加载,双重检查锁定)
public class LazySingleton {
private static volatile LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}volatile防止指令重排序导致未完全构造的对象被访问。private构造器防止外部new实例。- 枚举单例(
enum Singleton { INSTANCE })是最简单也最安全的写法。
工厂模式(Factory)
将对象创建的逻辑封装起来,客户端通过工厂获取实例,不直接 new。
简单工厂
public interface Payment {
void pay(double amount);
}
public class Alipay implements Payment {
public void pay(double amount) {
System.out.println("支付宝支付: " + amount);
}
}
public class WechatPay implements Payment {
public void pay(double amount) {
System.out.println("微信支付: " + amount);
}
}
public class PaymentFactory {
public static Payment create(String type) {
return switch (type) {
case "alipay" -> new Alipay();
case "wechat" -> new WechatPay();
default -> throw new IllegalArgumentException("未知支付方式: " + type);
};
}
}Payment payment = PaymentFactory.create("alipay");
payment.pay(100);工厂的优点:客户端代码不依赖具体实现类,新增支付方式只需加新类和修改工厂,无需修改调用方代码(符合开闭原则)。
Spring 的 BeanFactory
从本质上说,Spring 的 IoC 容器就是一个"超级工厂"——通过配置(XML、注解、Java Config)创建和管理对象,客户端通过 @Autowired 获取,完全不需要写 new。
策略模式(Strategy)
定义一组可互换的算法,让客户端在运行时选择使用哪个。
// 策略接口
public interface CompressionStrategy {
byte[] compress(byte[] data);
}
// 具体策略
public class ZipCompression implements CompressionStrategy {
public byte[] compress(byte[] data) {
System.out.println("使用 ZIP 压缩");
return data; // 实际压缩逻辑
}
}
public class GzipCompression implements CompressionStrategy {
public byte[] compress(byte[] data) {
System.out.println("使用 GZIP 压缩");
return data;
}
}
// 上下文
public class Compressor {
private final CompressionStrategy strategy;
public Compressor(CompressionStrategy strategy) {
this.strategy = strategy;
}
public byte[] compress(byte[] data) {
return strategy.compress(data);
}
}Compressor zip = new Compressor(new ZipCompression());
Compressor gzip = new Compressor(new GzipCompression());策略模式在 JDK 中的应用:Comparator 接口——Collections.sort(list, comparator) 中的 comparator 就是一个策略。
观察者模式(Observer)
定义一对多的依赖关系,一个对象状态变化时,所有依赖者自动收到通知。
// 事件
public record OrderEvent(long orderId, String status) {}
// 观察者接口
public interface OrderObserver {
void onOrderCreated(OrderEvent event);
}
// 被观察者
public class OrderService {
private final List<OrderObserver> observers = new ArrayList<>();
public void addObserver(OrderObserver observer) {
observers.add(observer);
}
public void createOrder(long orderId) {
System.out.println("创建订单: " + orderId);
OrderEvent event = new OrderEvent(orderId, "CREATED");
observers.forEach(o -> o.onOrderCreated(event));
}
}OrderService service = new OrderService();
service.addObserver(event -> System.out.println("发送邮件: " + event.orderId()));
service.addObserver(event -> System.out.println("记录日志: " + event.orderId()));
service.createOrder(1001);观察者模式在 Java 中的应用:
- Swing/AWT 的事件监听器。
- Spring 的
ApplicationEvent+@EventListener。 - 响应式编程(Reactive Streams)中的
Publisher/Subscriber。
小结
- 设计模式是解决特定问题的可复用思路,而非死板的代码模板。
- 单例模式保证一个类只有一个实例,注意线程安全和序列化问题。
- 工厂模式封装对象创建,客户端面向接口而非实现编程。
- 策略模式让算法可互换,
Comparator是 JDK 中最典型的示例。 - 观察者模式实现事件驱动,Spring 的事件机制是其经典应用。
- 易错:不要过度设计——简单的
if-else或switch能解决的问题无需强行套用模式。模式的使用时机应是"当前代码确实存在重复或难以扩展的问题",而非"为了用模式而用模式"。 - 思考任务:阅读 Spring Framework 或 JDK 源码(如 java.util.Collections、org.springframework.context.ApplicationListener),找出一处模式的应用,并说明它解决了什么问题。
上一节:Spring Boot 基础
