第13篇:深入探讨设计模式与Java实践
设计模式是解决软件设计中常见问题的经验总结,是构建可维护、可扩展代码的基石。本文将从 设计模式分类 、六大核心原则 出发,深入解析23种经典设计模式在Java中的实现,并结合Spring框架、JDK源码及实际场景,探讨模式的应用与演进。
1. 设计模式核心原则
原则 | 核心思想 | 典型应用场景 |
---|---|---|
开闭原则 (OCP) | 对扩展开放,对修改关闭 | 通过抽象层扩展功能(策略模式) |
单一职责 (SRP) | 一个类只负责一个功能领域 | 拆分臃肿类(状态模式) |
里氏替换 (LSP) | 子类必须能替换父类且不影响程序正确性 | 继承体系设计(模板方法模式) |
接口隔离 (ISP) | 客户端不应依赖它不需要的接口 | 拆分庞大接口(适配器模式) |
依赖倒置 (DIP) | 高层模块不依赖低层模块,两者依赖抽象 | 依赖注入(Spring IoC) |
迪米特法则 (LoD) | 减少对象间的耦合,只与直接朋友通信 | 门面模式封装子系统交互 |
2. 创建型模式:对象创建的艺术
2.1 工厂方法模式(Factory Method)
意图:定义创建对象的接口,让子类决定实例化哪个类。
java
// 抽象产品
interface Logger {
void log(String message);
}
// 具体产品
class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("File: " + message);
}
}
// 抽象工厂
interface LoggerFactory {
Logger createLogger();
}
// 具体工厂
class FileLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
return new FileLogger();
}
}
// 使用
LoggerFactory factory = new FileLoggerFactory();
Logger logger = factory.createLogger();
logger.log("Test message");
应用场景:
- JDK中的
Calendar.getInstance()
- Spring的
BeanFactory
2.2 抽象工厂模式(Abstract Factory)
意图:创建相关或依赖对象的家族,而无需指定具体类。
java
// 抽象产品族
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 具体工厂(Windows风格)
class WinFactory implements GUIFactory {
public Button createButton() { return new WinButton(); }
public Checkbox createCheckbox() { return new WinCheckbox(); }
}
// 客户端代码
public class Application {
private GUIFactory factory;
public Application(GUIFactory factory) {
this.factory = factory;
}
public void render() {
Button btn = factory.createButton();
btn.paint(); // 输出Windows风格按钮
}
}
典型应用:
- Java Swing的
LookAndFeel
- 数据库连接工厂(MySQL/Oracle驱动)
3. 结构型模式:构建灵活架构
3.1 适配器模式(Adapter)
意图:转换接口使得不兼容的类可以协作。
java
// 目标接口(客户端期望的接口)
interface MediaPlayer {
void play(String audioType, String fileName);
}
// 被适配者(已有实现)
class Mp4Player {
void playMp4(String fileName) {
System.out.println("Playing MP4: " + fileName);
}
}
// 适配器
class Mp4Adapter implements MediaPlayer {
private Mp4Player mp4Player = new Mp4Player();
@Override
public void play(String audioType, String fileName) {
if ("mp4".equalsIgnoreCase(audioType)) {
mp4Player.playMp4(fileName);
}
}
}
// 使用
MediaPlayer player = new Mp4Adapter();
player.play("mp4", "movie.mp4");
JDK实例:
Arrays.asList()
将数组适配为List- Spring MVC的
HandlerAdapter
3.2 装饰器模式(Decorator)
意图:动态地为对象添加职责。
java
// 组件接口
interface Coffee {
double getCost();
String getDescription();
}
// 具体组件
class SimpleCoffee implements Coffee {
public double getCost() { return 2.0; }
public String getDescription() { return "Simple Coffee"; }
}
// 装饰器基类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
}
// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public double getCost() {
return decoratedCoffee.getCost() + 0.5;
}
public String getDescription() {
return decoratedCoffee.getDescription() + ", Milk";
}
}
// 使用
Coffee coffee = new MilkDecorator(new SimpleCoffee());
System.out.println(coffee.getDescription()); // "Simple Coffee, Milk"
JDK应用:
- Java IO流体系(如
BufferedReader
装饰FileReader
)
4. 行为型模式:对象间的协作
4.1 策略模式(Strategy)
意图:定义算法族,封装每个算法,使它们可互换。
java
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略
class CreditCardPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid $" + amount + " via Credit Card");
}
}
class PayPalPayment implements PaymentStrategy {
public void pay(double amount) {
System.out.println("Paid $" + amount + " via PayPal");
}
}
// 上下文
class ShoppingCart {
private PaymentStrategy strategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void checkout(double amount) {
strategy.pay(amount);
}
}
// 使用
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(100.0);
应用场景:
- Java的
Comparator
排序策略 - Spring的
ResourceLoader
策略
4.2 观察者模式(Observer)
意图:定义对象间的一对多依赖,当一个对象状态改变时,自动通知依赖对象。
java
// 主题接口
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 具体主题
class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>();
private float temperature;
public void setTemperature(float temp) {
this.temperature = temp;
notifyObservers();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void notifyObservers() {
observers.forEach(o -> o.update(temperature));
}
}
// 观察者接口
interface Observer {
void update(float temperature);
}
// 具体观察者
class Display implements Observer {
public void update(float temperature) {
System.out.println("Current temp: " + temperature);
}
}
// 使用
WeatherStation station = new WeatherStation();
station.registerObserver(new Display());
station.setTemperature(25.5f); // 触发通知
JDK实现:
java.util.Observable
(已过时,建议自定义实现)- Spring的事件发布机制
ApplicationEventPublisher
5. 模式演进与框架实践
5.1 Spring框架中的模式应用
模式 | Spring实现示例 | 作用 |
---|---|---|
工厂模式 | BeanFactory |
管理Bean的创建 |
代理模式 | AOP的动态代理(JDK/CGLIB) | 实现事务管理、日志切面 |
模板方法 | JdbcTemplate |
封装JDBC流程 |
单例模式 | Bean的默认作用域 | 保证容器中Bean唯一 |
5.2 Java Stream API中的模式
- 建造者模式 :
Stream.Builder
构建复杂流 - 策略模式 :通过Lambda传递不同行为(如
filter
、map
) - 迭代器模式 :
Spliterator
实现并行遍历
6. 反模式与最佳实践
6.1 常见误用场景
- 单例模式滥用:导致测试困难、隐藏依赖关系
- 过度使用继承:违反组合优于继承原则
- 为模式而模式:增加不必要的复杂性
6.2 设计原则实践
java
// 违反开闭原则的代码
class ReportGenerator {
public void generate(String type) {
if ("PDF".equals(type)) {
// PDF生成逻辑
} else if ("CSV".equals(type)) {
// CSV生成逻辑
}
// 新增类型需修改代码
}
}
// 改进:使用策略模式
interface ReportStrategy {
void generate();
}
class PdfStrategy implements ReportStrategy { /* ... */ }
class CsvStrategy implements ReportStrategy { /* ... */ }
class ReportGenerator {
private ReportStrategy strategy;
public void setStrategy(ReportStrategy strategy) {
this.strategy = strategy;
}
public void generate() {
strategy.generate();
}
}
7. 现代架构中的模式演进
7.1 响应式编程与观察者模式
Reactive Streams规范(Publisher
/Subscriber
)是观察者模式的扩展:
java
Flux.interval(Duration.ofSeconds(1))
.map(i -> "Event " + i)
.subscribe(System.out::println); // 订阅者
7.2 函数式编程与策略模式
通过Lambda简化策略实现:
java
List<Integer> numbers = Arrays.asList(3, 1, 4);
numbers.sort((a, b) -> b.compareTo(a)); // 降序策略
8. 总结与进阶指南
-
模式选择原则:
- 优先使用组合而非继承
- 识别变化点,封装不稳定部分
- 避免过度设计,保持代码简洁
-
学习路径建议:
- 精读《设计模式:可复用面向对象软件的基础》(GoF)
- 分析JDK和主流框架源码中的模式应用
- 通过重构实践应用模式(如替换条件语句为策略模式)
-
工具支持:
- IDE插件(如IntelliJ IDEA的Pattern Analysis)
- 架构守护工具(ArchiUnit验证架构约束)
附:23种设计模式速查表
分类 | 模式名称 | 核心场景 |
---|---|---|
创建型 | 单例、工厂方法、抽象工厂、建造者、原型 | 对象创建解耦 |
结构型 | 适配器、桥接、组合、装饰器、门面、享元、代理 | 类与对象的结构组织 |
行为型 | 责任链、命令、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者 | 对象间的职责分配与通信 |
掌握设计模式不仅是学习解决方案,更是培养面向对象设计思维的过程。通过模式语言与持续实践,开发者能够构建出高内聚、低耦合的优雅系统架构。