首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

创建型模式实战:单例、工厂模式解析与 Spring 集成

  • 25-04-18 07:21
  • 3854
  • 9166
juejin.cn

创建型模式实战:单例、工厂模式解析与 Spring 集成

一、单例模式:全局唯一实例的正确打开方式

1.1 核心定义与应用场景

定义:确保一个类仅有一个实例,并提供全局访问点核心价值:

  • 避免资源重复创建(如数据库连接池、线程池)

  • 全局状态管理(如配置中心、日志管理器)

Spring 场景:

  • Bean 默认作用域为单例(@Scope("singleton"))

  • 应用上下文ApplicationContext本身是单例

1.2 五种实现方式对比

1.2.1 饿汉式(线程安全,立即加载)
java
代码解读
复制代码
// 优点:简单可靠,类加载时创建实例 // 缺点:可能造成资源浪费(未使用时也会创建) public class HungrySingleton { private static final HungrySingleton instance = new HungrySingleton(); private HungrySingleton() {} public static HungrySingleton getInstance() { return instance; } }
1.2.2 懒汉式(非线程安全,延迟加载)
java
代码解读
复制代码
// 反模式:多线程下可能创建多个实例 public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); // 非原子操作 } return instance; } }
1.2.3 双重检查锁定(线程安全,延迟加载)
java
代码解读
复制代码
// 正确实现:volatile禁止指令重排 public class DoubleCheckSingleton { private static volatile DoubleCheckSingleton instance; private DoubleCheckSingleton() {} public static DoubleCheckSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckSingleton.class) { if (instance == null) { instance = new DoubleCheckSingleton(); } } } return instance; } }
1.2.4 枚举单例(最简实现,线程安全)
java
代码解读
复制代码
// 优点:天然支持序列化/反序列化安全 public enum EnumSingleton { INSTANCE; public void doSomething() { /* 业务逻辑 */ } }
1.2.5 Spring Bean 单例(容器管理)
java
代码解读
复制代码
// 声明单例Bean(默认作用域) @Service public class SpringSingletonService { // 依赖注入支持 private final DataSource dataSource; @Autowired public SpringSingletonService(DataSource dataSource) { this.dataSource = dataSource; } }

1.3 线程安全与性能对比

实现方式线程安全延迟加载序列化安全Spring 集成
饿汉式是否是手动实现
双重检查锁定是是否(需额外处理)推荐方式
枚举单例是是是不适用
Spring Bean是是是内置支持

二、工厂模式:对象创建逻辑的封装与扩展

2.1 三种子模式对比解析

2.1.1 简单工厂(静态工厂)

场景:创建逻辑简单,无需扩展

java
代码解读
复制代码
// 日志工厂 public class LoggerFactory { public static Logger createLogger(String type) { if ("file".equals(type)) { return new FileLogger(); } else if ("console".equals(type)) { return new ConsoleLogger(); } throw new IllegalArgumentException("不支持的日志类型"); } }
2.1.2 工厂方法(多态工厂)

场景:需要支持多种产品类型扩展

2.1.3 抽象工厂(产品族创建)

场景:创建相关联的产品族(如数据库连接 + 操作对象)

java
代码解读
复制代码
// 抽象工厂接口 public interface DatabaseFactory { Connection createConnection(); Statement createStatement(); } // MySQL工厂实现 public class MySQLFactory implements DatabaseFactory { public Connection createConnection() { /* 创建MySQL连接 */ } public Statement createStatement() { /* 创建MySQL Statement */ } }

2.2 Spring 中的工厂模式实践

2.2.1 BeanFactory 核心实现
java
代码解读
复制代码
// 工厂方法模式 public interface BeanFactory { T getBean(Class requiredType); } // 具体工厂:DefaultListableBeanFactory public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry { @Override public T getBean(Class requiredType) { return doGetBean(requiredType.getName(), requiredType, null, false); } }
2.2.2 工厂 Bean 扩展点
java
代码解读
复制代码
// 自定义工厂Bean public class DataSourceFactoryBean implements FactoryBean { private String url; private String username; public void setUrl(String url) { this.url = url; } public DataSource getObject() { return DriverManager.getConnection(url, username, "password"); } public Class getObjectType() { return DataSource.class; } } // Spring配置 "dataSource" class="DataSourceFactoryBean"> "url" value="jdbc:mysql://localhost:3306/test" />

2.3 适用场景决策树

是
简单扩展
复杂产品族
否
是
否
是否需要封装对象创建逻辑?
是否需要支持扩展?
工厂方法模式
抽象工厂模式
是否需要静态便捷访问?
简单工厂模式
直接创建对象

三、企业级应用避坑指南

3.1 单例模式常见陷阱

  1. 序列化安全问题:
java
代码解读
复制代码
protected Object readResolve() { return instance; }
    • 反例:未实现readResolve()导致反序列化创建新实例
    • 解决方案:枚举单例或重写反序列化方法
  1. Spring 单例与线程安全:
    • 误区:单例 Bean 存储成员变量导致线程安全问题
    • 最佳实践:Bean 保持无状态,依赖注入的对象为线程安全类型

3.2 工厂模式过度设计预警

  1. 简单场景复杂化:
    • 反例:将简单对象(如Date)的创建用工厂模式封装
    • 原则:当创建逻辑包含复杂条件判断或资源管理时再使用
  1. 产品接口膨胀:
    • 反例:抽象工厂包含过多不相关产品接口
    • 解决方案:拆分为多个工厂或使用构建者模式

四、微服务场景中的模式应用

4.1 单例模式在配置中心的应用

java
代码解读
复制代码
// 分布式配置中心单例 public class ConfigCenter { private static final ConfigCenter instance; private final Map configs; private ConfigCenter() { configs = loadFromNacos(); // 从Nacos加载配置 } // 双重检查锁定实现 public static ConfigCenter getInstance() { /* ... */ } }

4.2 工厂模式在服务实例创建中的应用

java
代码解读
复制代码
// 微服务客户端工厂 public class MicroServiceClientFactory { public static T createClient(Class serviceClass) { String serviceName = serviceClass.getAnnotation(FeignClient.class).value(); return Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()) .target(serviceClass, "http://" + serviceName); } }

五、总结:创建型模式的本质

创建型模式的核心是分离对象创建逻辑,通过封装、继承、多态解决以下问题:

  1. 对象创建复杂性:隐藏具体实现细节(如单例的线程安全逻辑)

  2. 扩展性需求:支持新类型扩展而不修改现有代码(工厂方法模式)

  3. 全局唯一性:确保关键资源仅有一个实例(单例模式)

下一篇我们将继续探索创建型模式的另外两种:建造者模式(复杂对象构建)和原型模式(对象克隆与性能优化),并解析它们在 MyBatis、JPA 等框架中的实际应用。

这篇博客通过以下设计强化技术深度与实战价值:

  1. 实现对比:详细解析五种单例模式的线程安全与适用场景,提供 Spring Bean 单例的正确使用方式

  2. 模式演进:通过工厂模式三种子模式的类图与代码示例,展示从简单到复杂的设计演进过程

  3. 框架集成:深入 Spring BeanFactory 源码,演示工厂模式在容器中的核心作用

  4. 避坑指南:针对单例序列化安全、工厂模式过度设计等常见问题提供解决方案

注:本文转载自juejin.cn的AronTing的文章"https://juejin.cn/post/7493750880195477514"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top