Java 设计模式~工厂模式
在java开发,工厂模式应用场景有哪些?在Spring boot原码中 有哪些工厂类,并做相应的代码介绍。
工厂模式
工厂模式(Factory Pattern)是Java中一种常用的创建型设计模式,它提供了一种创建对象的最佳方式。此模式定义一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂模式让一个类的实例化延迟到其子类。
工厂模式的分类
- 简单工厂模式(Simple Factory Pattern):
- 又称静态工厂方法模式,它不属于GOF的23种设计模式之一,但在实际开发中经常使用。
- 通过一个工厂类来创建对象,客户端不需要直接实例化对象,而是通过调用工厂类的方法来获取对象实例。
- 工厂方法模式(Factory Method Pattern):
- 定义一个用于创建对象的接口,但由子类决定要实例化的类是哪一个。
- 工厂方法让一个类的实例化延迟到其子类,子类可以重写父类的工厂方法来指定实例化哪一个类。
- 抽象工厂模式(Abstract Factory Pattern):
- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 抽象工厂模式使得客户端可以独立于它的产品的具体类变化,客户端通过它们的抽象接口操纵实例。
工厂模式的优缺点
优点:
- 封装性:使用工厂模式可以将对象的创建过程封装起来,使得客户端代码与具体实现类解耦,降低了代码的耦合度。
- 可扩展性:当需要添加新的产品时,只需要在工厂类中添加相应的创建逻辑即可,不需要修改客户端代码,符合开闭原则。
- 灵活性:工厂模式可以灵活地创建对象,可以通过不同的工厂类来创建不同的对象实例。
缺点:
- 复杂性:增加了系统的复杂性,因为需要引入工厂类和抽象类或接口。
- 性能开销:在创建对象时,需要调用工厂类的方法,可能会增加一些性能开销。
工厂模式的实现示例
以下是简单工厂模式的实现示例:
java复制代码
// 产品接口 | |
public interface Product { | |
void use(); | |
} | |
// 具体产品类A | |
public class ProductA implements Product { | |
@Override | |
public void use() { | |
System.out.println("使用产品A"); | |
} | |
} | |
// 具体产品类B | |
public class ProductB implements Product { | |
@Override | |
public void use() { | |
System.out.println("使用产品B"); | |
} | |
} | |
// 工厂类 | |
public class SimpleFactory { | |
public static Product createProduct(String type) { | |
Product product = null; | |
switch (type) { | |
case "A": | |
product = new ProductA(); | |
break; | |
case "B": | |
product = new ProductB(); | |
break; | |
default: | |
throw new IllegalArgumentException("未知的产品类型"); | |
} | |
return product; | |
} | |
} | |
// 客户端代码 | |
public class Client { | |
public static void main(String[] args) { | |
Product productA = SimpleFactory.createProduct("A"); | |
productA.use(); | |
Product productB = SimpleFactory.createProduct("B"); | |
productB.use(); | |
} | |
} |
在上面的示例中,SimpleFactory是一个简单工厂类,它有一个静态方法createProduct,根据传入的类型参数来创建不同的Product对象。客户端代码通过调用SimpleFactory.createProduct方法来获取产品对象,并调用其use方法。
通义灵码
在Java开发中,工厂模式有多种应用场景,主要集中在以下几个方面:
工厂模式的应用场景
- 解耦对象的创建和使用:通过工厂模式,客户端不需要知道对象的具体创建细节,只需要通过工厂获取对象即可。
- 动态选择对象的创建:可以根据不同的条件动态选择创建不同类型的对象。
- 集中管理对象的创建:适用于需要集中管理对象创建逻辑的场景。
- 简化复杂对象的创建过程:对于复杂的对象创建过程,可以使用工厂模式封装创建逻辑,简化客户端代码。
- 提高系统的可扩展性:新增产品类时,只需添加对应的工厂方法或工厂类,而不需要修改现有代码。
Spring Boot中的工厂类及其应用场景
1. BeanFactory
- 应用场景:
BeanFactory是Spring框架的核心接口之一,负责管理和配置应用程序中的bean。它是Spring容器的基础,提供了基本的依赖注入功能。 - 代码示例:
java
// 获取BeanFactory实例 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); MyBean myBean = (MyBean) context.getBean("myBean");
2. ApplicationContext
- 应用场景:
ApplicationContext是BeanFactory的一个子接口,提供了更多的企业级功能,如国际化支持、事件传播机制等。它是Spring Boot中最常用的容器。 - 代码示例:
java
// 获取ApplicationContext实例 ApplicationContext context = SpringApplication.run(MyApplication.class, args); MyService myService = context.getBean(MyService.class);
3. ObjectFactory
- 应用场景:
ObjectFactory通常用于延迟初始化对象,当需要时才创建对象。它常用于复杂的依赖关系中,以提高性能。 - 代码示例:
java
@Component public class MyComponent { private final ObjectFactory<MyDependency> myDependencyFactory; @Autowired public MyComponent(ObjectFactory<MyDependency> myDependencyFactory) { this.myDependencyFactory = myDependencyFactory; } public void doSomething() { MyDependency myDependency = myDependencyFactory.getObject(); // 使用myDependency } }
4. FactoryBean
- 应用场景:
FactoryBean接口允许自定义bean的创建逻辑。当你需要复杂的bean初始化过程时,可以实现这个接口。 - 代码示例:
java
@Component public class MyFactoryBean implements FactoryBean<MyBean> { @Override public MyBean getObject() throws Exception { return new MyBean(); // 自定义创建逻辑 } @Override public Class<?> getObjectType() { return MyBean.class; } }
5. SmartFactoryBean
- 应用场景:
SmartFactoryBean是FactoryBean的一个扩展接口,提供了更多的控制选项,如是否单例、是否需要运行时检查等。 - 代码示例:
java
@Component public class MySmartFactoryBean implements SmartFactoryBean<MyBean> { @Override public MyBean getObject() throws Exception { return new MyBean(); // 自定义创建逻辑 } @Override public Class<?> getObjectType() { return MyBean.class; } @Override public boolean isSingleton() { return true; // 是否为单例 } }
Spring Boot源码中的工厂类示例
DefaultListableBeanFactory
- 应用场景:
DefaultListableBeanFactory是BeanFactory的一个实现类,提供了对bean定义的注册和管理功能。 - 代码示例:
java
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); BeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(new FileSystemResource("beans.xml")); MyBean myBean = (MyBean) beanFactory.getBean("myBean");
AnnotationConfigApplicationContext
- 应用场景:
AnnotationConfigApplicationContext是ApplicationContext的一个实现类,用于从Java配置类中加载bean定义。 - 代码示例:
java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MyService myService = context.getBean(MyService.class);
SimpleObjectFactory
- 应用场景:
SimpleObjectFactory是Spring内部使用的简单对象工厂,用于创建对象实例。 - 代码示例:
java
SimpleObjectFactory factory = new SimpleObjectFactory(); MyBean myBean = factory.createObjectInstance(MyBean.class);
AutowireCapableBeanFactory
- 应用场景:
AutowireCapableBeanFactory是BeanFactory的一个扩展接口,提供了自动装配功能。 - 代码示例:
java
AutowireCapableBeanFactory beanFactory = new DefaultListableBeanFactory(); MyBean myBean = beanFactory.createBean(MyBean.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
这些工厂类在Spring Boot中扮演着重要的角色,帮助开发者更高效地管理和创建对象。根据具体的应用场景,可以选择合适的工厂类来实现需求。
文兴一言
Java开发中工厂模式的应用场景
工厂模式在Java开发中具有广泛的应用场景,主要包括以下几个方面:
- 对象创建复杂:当对象的创建过程涉及多个步骤或需要复杂的配置时,可以使用工厂模式来封装这些创建逻辑,简化客户端代码。
- 需要创建的对象类型较多:如果系统中需要根据不同的条件创建不同类型的对象,使用工厂模式可以避免大量的if-else或switch-case语句,使代码更加清晰和易于维护。
- 提高代码的可测试性:在单元测试时,工厂模式允许创建模拟(mock)对象,以便在不依赖实际对象的情况下测试代码。
- 遵循开闭原则:工厂模式使得系统能够在不修改现有代码的情况下添加新的产品类型或创建逻辑,符合开闭原则(对扩展开放,对修改关闭)。
Spring Boot源码中的工厂类
在Spring Boot源码中,工厂模式得到了广泛的应用。以下是一些常见的工厂类及其代码介绍:
-
SpringFactoriesLoaderSpringFactoriesLoader是Spring Boot用于加载工厂类的关键类。它负责从类路径中的META-INF/spring.factories文件中加载工厂类的名称,并实例化这些工厂类。这个文件以键值对的形式存在,键是接口类的全限定名,值是用逗号隔开的多个实现类的全限定名。java复制代码private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}在上面的代码中,
getSpringFactoriesInstances方法负责加载和实例化spring.factories文件中指定的工厂类。 -
ApplicationContextInitializer工厂ApplicationContextInitializer是Spring Boot用于初始化ApplicationContext的接口。Spring Boot在启动时会加载并调用这些初始化器来配置ApplicationContext。这些初始化器通常通过@Configuration注解定义的配置类来创建。java复制代码@Configurationpublic class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {// 初始化逻辑}}在
spring.factories文件中,可以通过指定org.springframework.context.ApplicationContextInitializer的键来注册这些初始化器。 -
ApplicationListener工厂ApplicationListener是Spring框架中的事件监听器接口。在Spring Boot中,可以通过实现这个接口来监听特定的事件,并在事件发生时执行相应的逻辑。这些监听器通常也是通过@Configuration注解定义的配置类来创建的。java复制代码@Componentpublic class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {@Overridepublic void onApplicationEvent(ApplicationReadyEvent event) {// 事件处理逻辑}}与
ApplicationContextInitializer类似,ApplicationListener也可以通过在spring.factories文件中指定相应的键来注册。 -
自定义工厂类
除了Spring Boot自带的工厂类外,开发者还可以根据自己的需求创建自定义的工厂类。这些工厂类通常用于封装复杂的对象创建逻辑,以便在需要时轻松地创建对象实例。
java复制代码@Configurationpublic class MyFactoryConfig {@Beanpublic MyService myService() {return new MyServiceImpl();}}public interface MyService {void performService();}public class MyServiceImpl implements MyService {@Overridepublic void performService() {// 服务实现逻辑}}在上面的代码中,
MyFactoryConfig是一个配置类,它定义了一个工厂方法myService来创建MyService接口的实现类MyServiceImpl的实例。这样,当需要MyService类型的对象时,Spring容器会自动调用这个工厂方法来创建实例。
综上所述,工厂模式在Java开发和Spring Boot源码中都具有广泛的应用。通过合理地使用工厂模式,可以简化对象创建逻辑、提高代码的可读性和可维护性,并遵循开闭原则以支持系统的扩展性。
相关文章:
Java 设计模式~工厂模式
在java开发,工厂模式应用场景有哪些?在Spring boot原码中 有哪些工厂类,并做相应的代码介绍。 工厂模式 工厂模式(Factory Pattern)是Java中一种常用的创建型设计模式,它提供了一种创建对象的最佳方式。此…...
OmicsTools生信环境全自动化安装配置教程,代做生信分析和辅导
OmicsTools软件介绍和下载安装配置 软件介绍 我开发了一款本地电脑无限使用的零代码生信数据分析作软图神器电脑软件OmicsTools,旨在成为可以做各种医学生物生信领域科研数据分析作图的的全能科研软件,欢迎大家使用OmicsTools进行生物医学科研数据分析…...
鸿蒙HarmonyOS应用开发 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
鸿蒙心路旅程:探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力 HarmonyOS Next 是华为推出的全新一代操作系统,旨在进一步推动分布式技术的深度应用和生态融合。本文将从技术特点、应用场景入手,通过实战案例与代码示例&…...
二分模板题
题目传送门 主要思路: 暴力会tle n的3次方了然后 二分可以找中间然后去二分枚举两边 最后结果 ansa小于它的数*c大于它的数 注意要判断是否符合条件 即如果a的小于它的数还大于它就不成立 或者c的数小于它也不成立结果 要注意转long long ans(long long)tp1*tp2; …...
一篇文章掌握Git的基本原理与使用
目录 一、创建仓库 1.1 git init 1.2 git clone 二、工作区域与文件状态 三、添加和提交文件 3.1 git status 3.2 git add git rm --cached 3.3 git commit git log 四、版本回退 soft hard mixed 总结 五、查看差异 工作区与暂存区 工作区与本地仓库 暂存区…...
「Mac畅玩鸿蒙与硬件43」UI互动应用篇20 - 闪烁按钮效果
本篇将带你实现一个带有闪烁动画的按钮交互效果。通过动态改变按钮颜色,用户可以在视觉上感受到按钮的闪烁效果,提升界面互动体验。 关键词 UI互动应用闪烁动画动态按钮状态管理用户交互 一、功能说明 闪烁按钮效果应用实现了一个动态交互功能…...
朗新科技集团如何用云消息队列 RocketMQ 版“快、准、狠”破解业务难题?
作者:邹星宇、刘尧 朗新科技集团:让数字化的世界更美好 朗新科技集团股份有限公司是领先的能源科技企业,长期深耕电力能源领域,通过新一代数字化、人工智能、物联网、电力电子技术等新质生产力,服务城市、产业、生活中…...
【Ubuntu】Ubuntu的Desktop(学习/用户使用)和Bit版本(工作)
这篇文章似乎没什么必要写,但想了想还是决定记录一下,也许对新手入坑Ubuntu会有帮助, 事实上也很简单,一个是桌面版本,另一个是字符界面版本。 桌面版:拥有图形桌面 字符界面,易上手ÿ…...
cmake CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_LIST_DIR的区别
在 CMake 中,CMAKE_CURRENT_LIST_DIR 和 CMAKE_CURRENT_SOURCE_DIR 都是指代当前 CMake 文件所在的路径,但它们的含义和用途有所不同: CMAKE_CURRENT_LIST_DIR: 表示 当前处理的 CMake 文件(例如 CMakeLists.txt&#…...
学会用VSCode debug
本文主要介绍了 VS Code 的调试功能,包括其强大的内置调试器,支持多种语言,如 JavaScript、TypeScript 等。通过简单项目示例展示调试过程,还介绍了运行面板和菜单、启动配置、调试操作、断点、记录点等功能,以及三种调…...
C语言专题之结构体的使用
结构体(struct)是一种用户自定义的数据类型,它允许将不同类型的数据组合在一起,形成一个新的数据类型。结构体在编程中非常常见,尤其是在需要处理复杂数据结构的情况下。以下是结构体的基本使用方法: 一、结…...
python中的高阶函数
1、什么是高阶函数? 高阶函数是指将函数作为参数传入。就是高阶函数 2、高阶函数有哪些? map 映射函数 >>> print(list(map(lambda x:x*x,range(1,11)))) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] >>> print(list(map(lambda x:st…...
学习笔记063——通过使用 aspose-words 将 Word 转 PDF 时,遇到的字体改变以及乱码问题
文章目录 1、问题描述:2、解决方法: 1、问题描述: Java项目中,有个需要将word转pdf的需求。本人通过使用aspose-words来转换的。在Windows中,转换是完全正常的。但是当部署到服务器时,会出现转换生成的pdf…...
SpringBoot整合Mockito进行单元测试超全详细教程 JUnit断言 Mockito 单元测试
Mock概念 Mock叫做模拟对象,即用来模拟未被实现的对象可以预先定义这个对象在特定调用时的行为(例如返回值或抛出异常),从而模拟不同的系统状态。 导入Mock依赖 pom文件中引入springboot测试依赖,spring-boot-start…...
【AI知识】过拟合、欠拟合和正则
一句话总结: 过拟合和欠拟合是机器学习中的两个相对的概念,正则化是用于解决过拟合的方法。 1. 欠拟合: 指模型在训练数据上表现不佳,不能充分捕捉数据的潜在规律,导致在训练集和测试集上的误差都很高。欠拟合意味着模…...
MacOS编译webRTC源码小tip
简单记录一下,本人在编译webRTC时,碰到了一下比较烦人的问题,在MacOS终端下,搭建科学上网之后,chromium的depot_tools仓库成功拉下来了,紧接着,使用fetch以及gclient sync始终都返回curl相关的网…...
Linux基础命令(三):文件压缩及解压缩命令
文件压缩及解压缩命令 tar — 打包和压缩 tar 是一个用于打包文件的工具,常常用来将多个文件或目录打包成一个单独的文件。它本身不进行压缩,但可以与压缩工具(如 gzip 或 bzip2)一起使用。 用法: 打包文件࿰…...
目标跟踪算法:ByteTrack、卡尔曼滤波、匈牙利算法、高置信度检测目标、低置信度检测目标
目录 1 ByteTrack特点 2 ByteTrack和SORT区别----个人通俗理解 3 ByteTrack算法原理 4 ByteTrack整体流程图 上一篇博客我复习了下SORT跟踪算法,这一篇博客我再复习下ByteTrack跟踪算法,ByteTrack里面也是用了卡尔曼滤波和匈牙利算法&#x…...
[定昌linux系统]如何安装jdk8
1:下载jdk8 的 arm64 的版本,由于官方下载需要gmail,我的gmail 密码忘了,所以从csdn上下载了一份,地址: https://download.csdn.net/download/qq_27742163/88533548?utm_mediumdistribute.pc_relevant_download.none…...
【Cadence32】PCB多层板电源、地平面层创建心得➕CM约束管理器Analyze分析显示设置➕“DP”报错DRC
【转载】Cadence Design Entry HDL 使用教程 【Cadence01】Cadence PCB Edit相对延迟与绝对延迟的显示问题 【Cadence02】Allegro引脚焊盘Pin设置为透明 【Cadence03】cadence不小心删掉钢网层怎么办? 【Cadence04】一般情况下Allegro PCB设计时的约束规则设置&a…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
相关类相关的可视化图像总结
目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系,可直观判断线性相关、非线性相关或无相关关系,点的分布密…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
21-Oracle 23 ai-Automatic SQL Plan Management(SPM)
小伙伴们,有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL, 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始,OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…...
C#中用于控制自定义特性(Attribute)
我们来详细解释一下 [AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited false)] 这个 C# 属性。 在 C# 中,Attribute(特性)是一种用于向程序元素(如类、方法、属性等)添加元数据的机制。Attr…...
