框架中的设计模式实践:Spring与JDK的经典实现

设计模式是软件开发中的最佳实践总结,在Java生态中,Spring框架和JDK自身都大量运用了各种设计模式。本文将深入剖析这些经典实现,帮助开发者理解模式的实际应用场景。

一、Spring框架中的模式应用

1. 工厂模式(BeanFactory)

概念
BeanFactory是Spring IoC容器的核心接口,它实现了工厂模式,负责创建和管理应用中的对象(称为beans)。

实现原理

// 典型使用方式
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MyService service = context.getBean(MyService.class);

mermaid类图

图1

实践建议

  • 优先使用ApplicationContext而非直接使用BeanFactory,因为它提供了更多企业级功能
  • 理解bean的作用域(singleton/prototype等)对系统性能的影响
  • 利用@Configuration@Bean实现自定义工厂逻辑

2. 代理模式(AOP实现)

概念
Spring AOP通过代理模式实现横切关注点的模块化,主要分为JDK动态代理和CGLIB代理两种方式。

实现对比

特性JDK动态代理CGLIB代理
原理基于接口基于类继承
性能调用快,创建慢创建快,调用稍慢
限制必须实现接口无法代理final方法

示例代码

// 定义切面
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Executing: " + joinPoint.getSignature());
    }
}

实践建议

  • 对于性能敏感场景,考虑使用AspectJ编译时织入
  • 谨慎选择切入点表达式,避免过度拦截影响性能
  • 代理方法内部调用不会触发AOP,这是常见陷阱

3. 模板方法(JdbcTemplate)

概念
JdbcTemplate是模板方法模式的经典实现,封装了JDBC操作的固定流程,开发者只需关注SQL和结果处理。

核心流程

  1. 获取连接
  2. 创建语句
  3. 执行操作
  4. 处理结果
  5. 处理异常
  6. 释放资源

示例代码

public List<User> findAll() {
    return jdbcTemplate.query("SELECT * FROM users", (rs, rowNum) -> {
        User user = new User();
        user.setId(rs.getLong("id"));
        user.setName(rs.getString("name"));
        return user;
    });
}

实践建议

  • 利用NamedParameterJdbcTemplate提高SQL可读性
  • 对于复杂映射,考虑使用RowMapper实现类而非lambda
  • 批量操作使用batchUpdate()方法显著提高性能

二、JDK内置的模式实现

1. 观察者模式(java.util.Observable)

概念
Observable类和Observer接口构成了JDK对观察者模式的实现,允许对象间建立发布-订阅关系。

演进现状

  • Java 9开始Observable被标记为过时
  • 现代开发推荐使用java.beans.PropertyChangeSupport或反应式流(如RxJava)

经典实现

class WeatherData extends Observable {
    private float temperature;
    
    public void setTemperature(float temp) {
        this.temperature = temp;
        setChanged();  // 标记状态已改变
        notifyObservers();  // 通知观察者
    }
}

class Display implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        // 更新显示逻辑
    }
}

实践建议

  • 在新项目中避免直接使用Observable/Observer
  • 考虑使用PropertyChangeListener或反应式编程库
  • 注意线程安全问题,观察者通知通常发生在发布者线程

2. 迭代器模式(java.util.Iterator)

概念
迭代器模式提供了一种顺序访问集合元素的方法,而不暴露其底层表示。

JDK演进

  • Java 5引入Iterable接口和增强for循环
  • Java 8引入forEachRemaining默认方法

并发考虑

List<String> list = Collections.synchronizedList(new ArrayList<>());
// 需要客户端加锁的迭代
synchronized(list) {
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        System.out.println(it.next());
    }
}

实践建议

  • ArrayList等非线程安全集合,使用CopyOnWriteArrayList避免并发修改异常
  • Java 8+推荐使用forEach方法简化迭代代码
  • 实现自定义集合时,考虑实现Spliterator以支持并行流

3. 装饰器模式(java.io包)

概念
装饰器模式通过包装原始对象动态添加功能,java.io包是这一模式的典型应用。

类结构

图2

正确用法

// 多层装饰
try (InputStream is = new BufferedInputStream(
                     new GZIPInputStream(
                     new FileInputStream("data.gz")))) {
    // 读取处理
}

实践建议

  • 总是使用try-with-resources确保流正确关闭
  • 注意装饰顺序,比如缓冲流应该包装在最外层
  • 对于NIO场景,考虑使用ChannelsBuffers获得更好性能

三、模式选择的最佳实践

  1. 框架优先原则

    • 优先使用Spring或JDK内置的模式实现
    • 避免重复造轮子,但需理解底层原理
  2. 性能考量

    // 不好的做法:每次调用都创建新代理
    public void process() {
        Service proxy = createProxy(realService);  // 昂贵操作
        proxy.doSomething();
    }
  3. 可测试性

    • 依赖注入使模式实现更易测试
    • 使用Mockito等工具测试代理行为
  4. 现代Java特性结合

    // 使用Lambda简化观察者模式
    eventStream.subscribe(event -> {
        // 处理事件
    });

理解这些模式在框架中的实现,不仅能帮助我们更好地使用这些框架,还能在自定义开发中做出更合适的设计决策。记住,模式是手段而非目的,应根据实际场景灵活运用。

添加新评论