java设计模式学习之【工厂模式】
文章目录
- 引言
- 工厂方法模式简介
- 定义与用途:
- 实现方式:
- 使用场景
- 优势与劣势
- 工厂模式在spring中的应用
- 电费计算示例(简单工厂模式)
- 改善为方法工厂模式
- 代码地址
引言
在软件开发的世界中,对象的创建可能是一个复杂且重复的过程。为了简化这个过程,设计模式中的“工厂方法”就像一个小工厂,专门负责生产特定类型的对象。今天,我们来深入探索这个设计模式,看看它是如何让对象的创建变得简单又有趣。
工厂方法模式简介
工厂方法模式是一种创建型设计模式。 它通过使用一个工厂类来创建对象,而不是直接使用 new 运算符。这使得程序可以在不知道对象确切类型的情况下,生成对象的实例。
定义与用途:
- 工厂设计模式是一种创建型设计模式,广泛应用于JDK和像Spring、Struts这样的框架中。
- 当有一个超类和多个子类,并且基于输入返回其中一个子类时,使用工厂设计模式是非常合适的。
实现方式:
通过将类的实例化过程从客户端代码转移到工厂类,从而减少客户端的复杂性。
使用场景
- 当类的实例化过程复杂,需要依据不同的条件来创建不同的对象时。
- 当需要解耦对象的创建和使用时。
- 在提供一个类库,并希望只暴露接口而非实现细节时。
优势与劣势
- 优势
提高灵活性:可以在运行时选择创建哪个类的实例。
降低耦合度:客户端代码与具体类的创建过程解耦。
易于扩展:添加新的类不影响现有代码。 - 劣势
增加代码复杂性:可能会引入许多新类,增加系统的复杂性。
维护难度:当添加新类型时,可能需要修改工厂类。
工厂模式在spring中的应用
Spring框架广泛地应用了工厂模式,这是Spring框架中对象管理和依赖注入核心功能的基础。以下是Spring框架中使用工厂模式的几个关键地方:
BeanFactory:
Spring框架中最基本的容器,它提供了依赖注入(DI)的支持。
BeanFactory 使用工厂模式来实例化应用程序中的所有bean。
它使用 getBean 方法来创建bean实例。ApplicationContext:
它是 BeanFactory 的子接口,提供了更高级的特性,如事件传播、资源加载等。
ApplicationContext 本身也是一个大型工厂,用于创建并管理应用程序中的beans,以及提供对不同类型的bean的访问。FactoryBean:
Spring中特殊的bean类型,用于产生其他bean实例。
这种模式允许用户实现复杂的初始化逻辑,并通过Spring容器进行管理。BeanDefinition:
在Spring中,BeanDefinition 代表了bean的配置元数据,它将如何在Spring容器中创建bean的细节描述了出来。
通过这种方式,Spring使用工厂模式来创建具体的bean实例。单例模式与工厂模式的结合:
默认情况下,Spring容器中的所有bean都是单例的,这意味着每个bean都是全局唯一的并且在整个应用程序中共享。
Spring容器作为工厂,管理着这些单例bean的生命周期和实例化过程。依赖注入(DI):
虽然DI不是工厂模式,但它利用了工厂模式的概念来实现对象的创建和依赖的注入。
DI容器(如 Ap plicationContext)负责创建对象和管理它们的依赖关系,这在本质上是一种工厂模式的应用。
电费计算示例(简单工厂模式)
我们将创建一个名为 Plan 的抽象类以及继承该抽象类的具体类。下一步是定义一个名为 GetPlanFactory 的工厂类。
GenerateBill 类将使用 GetPlanFactory 来获取一个 Plan 对象。它将传递信息(DOMESTICPLAN / COMMERCIALPLAN / INSTITUTIONALPLAN)给 GetPlanFactory,以获取它所需的对象类型。

步骤 1: 创建抽象计划类
首先,我们定义一个抽象类 Plan,它包含了计算电费所必需的方法和属性。
abstract class Plan {protected double rate;abstract void getRate();public void calculateBill(int units) {System.out.println(units * rate);}
} //end of Plan class.
步骤 2: 定义具体计划类
接着,我们创建具体类 DomesticPlan、CommercialPlan 和 InstitutionalPlan,这些类继承自 Plan 并提供了 getRate 方法的具体实现。
class DomesticPlan extends Plan {public void getRate() {rate = 3.50;}
} //end of DomesticPlan class.class CommercialPlan extends Plan {public void getRate() {rate = 7.50;}
} //end of CommercialPlan class.class InstitutionalPlan extends Plan {public void getRate() {rate = 5.50;}
} //end of InstitutionalPlan class.
步骤 3: 创建工厂类
GetPlanFactory 是一个工厂类,根据传入的计划类型生成相应的计划对象。
class GetPlanFactory {public Plan getPlan(String planType) {if (planType == null) {return null;}if (planType.equalsIgnoreCase("DOMESTICPLAN")) {return new DomesticPlan();} else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {return new CommercialPlan();} else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {return new InstitutionalPlan();}return null;}
} //end of GetPlanFactory class.
步骤 4: 生成账单
GenerateBill 类使用 GetPlanFactory 来获取具体的计划对象,并根据使用的单位数计算电费。
class GenerateBill {public static void main(String args[]) throws IOException {GetPlanFactory planFactory = new GetPlanFactory();BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("Enter the name of plan for which the bill will be generated: ");String planName = br.readLine();System.out.print("Enter the number of units for bill will be calculated: ");int units = Integer.parseInt(br.readLine());Plan p = planFactory.getPlan(planName);System.out.print("Bill amount for " + planName + " of " + units + " units is: ");p.getRate();p.calculateBill(units);}
} //end of GenerateBill class.
以上就是一个简单的工厂模式示例代码,运行代码我们可以看到:
输入相应的计划就可以算出该类型下具体的电费。

改善为方法工厂模式
当新的计划类型增加时,GetPlanFactory 就需要修改。这违反了开闭原则(对扩展开放,对修改封闭)。
以上举例属于简单工厂模式接下来改为方法工厂模式。
改造步骤
- 创建一个抽象的工厂类或接口。
- 为每种计划类型创建具体的工厂类,继承自抽象工厂类或实现工厂接口。
- 每个具体工厂类实现创建相应产品对象的方法。
public abstract class GetPlanFactoryPro {abstract Plan getPlan();
}class DomesticPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new DomesticPlan();}
}class CommercialPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new CommercialPlan();}
}class InstitutionalPlanFactory extends GetPlanFactoryPro {@OverridePlan getPlan() {return new InstitutionalPlan();}
}
调用方法:
public class GenerateBillPro {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.print("Enter the name of plan for which the bill will be generated: ");String planName = br.readLine();System.out.print("Enter the number of units for bill will be calculated: ");int units = Integer.parseInt(br.readLine());GetPlanFactoryPro factory = getFactory(planName);if (factory == null) {System.out.println("Invalid Plan Type");return;}Plan p = factory.getPlan();System.out.print("Bill amount for " + planName + " of " + units + " units is: ");p.getRate();p.calculateBill(units);}private static GetPlanFactoryPro getFactory(String planType) {if (planType.equalsIgnoreCase("DOMESTICPLAN")) {return new DomesticPlanFactory();} else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {return new CommercialPlanFactory();} else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {return new InstitutionalPlanFactory();}return null;}}
**灵活性和扩展性:**通过使用工厂方法模式,我们增加了代码的灵活性和扩展性。如果要添加新的计划类型,只需增加一个新的工厂类,而无需修改现有的工厂逻辑或客户端代码。
**符合开闭原则:**工厂方法模式使得我们的代码更好地符合开闭原则,因为现在系统可以在不修改现有代码的情况下引入新类型的Plan。
缺点:
随着产品类的增加,相关的工厂类也会增加,可能导致系统类的数量增长。
代码地址
23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern
相关文章:
java设计模式学习之【工厂模式】
文章目录 引言工厂方法模式简介定义与用途:实现方式: 使用场景优势与劣势工厂模式在spring中的应用电费计算示例(简单工厂模式)改善为方法工厂模式代码地址 引言 在软件开发的世界中,对象的创建可能是一个复杂且重复的…...
android 内存分析(待续)
/proc/meminfo memory状态解读 命令:adb shell cat /proc/meminfo内存分布log 查看方式 命令:adb shell cat /proc/meminfo 用途:可以整体的了解memory使用情况 我们说的可用memory一般以MemAvailable的数据为准。所以了解MemAvailable的组成可以帮助…...
2023-简单点-机器学习中的数值计算问题
上溢和下溢: 上溢:指数函数或对数函数的输入值过大,导致计算结果超出了计算机可以表示的最大值。例如,在softmax函数中,当输入的数值很大时,指数运算的结果可能非常大,导致上溢。 下溢&#x…...
Qt5的事件处理函数有哪些?
2023年11月29日,周三上午 通过查看QWidget的定义可知,事件处理函数有: bool event(QEvent *event) override;virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *event);virtual void mouseDou…...
Jmeter性能综合实战——签到及批量签到
提取性能测试的三个方面:核心、高频、基础功能 签 到 请 求 步 骤 1、准备工作: 签到线程组 n HTTP请求默认值 n HTTP cookie 管理器 n 首页访问请求 n 登录请求 n 查看结果树 n 调试取样器 l HTTP代理服务器 (1)创建线…...
04 # 第一个 TypeScript 程序
初始化项目以及安装依赖 新建 ts_in_action 文件夾 npm init -y安装好 typescript,就可以执行下面命令查看帮助信息 npm i typescript -g tsc -h创建配置文件,执行下面命令就会生成一个 tsconfig.json 文件 tsc --init使用 tsc 编译一个 js 文件 新…...
Android gradle 配置阿里镜像
要在Android Gradle中配置阿里镜像,可以按照以下步骤进行操作: 打开项目中的 build.gradle 文件。 在 build.gradle 文件中添加阿里镜像的地址,如下所示: buildscript {repositories {maven { url https://maven.aliyun.com/re…...
Arduino驱动DHT20温湿度传感器(温湿度传感器)
目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 DHT20温湿度传感器是DHT11的全新升级版。 DHT20采用全新的ASIC专用芯片、改进的MEMS半导体电容式湿度传感器元件和标准片上温度元件。所有传感器均经过工厂校准,具有低功耗、高精度和稳定性、响应…...
如何使用ArcGIS Pro制作一张北极俯视地图
地图的表现形式有很多种,经常我们看到的地图是以大西洋为中心的地图,还有以太平洋为中心的地图,今天要给大家介绍的地图是从北极上方俯视看的地图,这里给大家讲解一下制作方法,希望能对你有所帮助。 修改坐标系 制作…...
每天五分钟计算机视觉:经典架构的力量与启示
在深度学习和计算机视觉领域,卷积神经网络(Convolutional Neural Networks,简称CNN)无疑是最为经典的架构之一。近年来,随着研究的不断深入和新架构的不断涌现,许多初学者可能会忽视这些经典架构的重要性。然而,理解并学习这些经典架构,对于我们深入理解卷积神经网络的…...
element plus 使用细节
菜鸟一直在纠结这个写不写,因为不难,但是菜鸟老是容易忘记,虽然想想或者搜搜就可以马上写出来,但是感觉每次那样就太麻烦了,不如一股做气写了算了,后面遇见别的就再来补充! 文章目录 table 表格…...
分析:为什么有些pdf打开之后无法编辑?
pdf文件大家应该都经常接触,但是不知道大家会遇到这种情况:有些PDF文件打开之后无法编辑?是什么原因呢?今天我们来分析一下都是那些原因导致的。 首先我们可以考虑一下,PDF文件中的内容是否是图片,如果确认…...
Django请求生命周期流程
浏览器发起请求。 先经过网关接口,Django自带的是wsgiref,请求来的时候解析封装,响应走的时候打包处理,这个wsgiref模块本身能够支持的并发量很少,最多1000左右,上线之后会换成uwsgi,并且还会加…...
C++学习 --string
目录 1, 什么是string 2, 创建string 3, 操作string 3-1, 赋值 3-1-1, 赋值() 3-1-1, 赋值(assign) 3-2, 修改 3-2-1, 拼接 3-2-1-1, 拼接() 3-2-1-2ÿ…...
Spark SQL,DF,RDD cache常用方式
RDD中的cache 调用cache方法 val testRDD sc.parallelize(Seq(elementA, elementB, elementC)).map(x > (x._1, x._2)).setName("testRDD")testRDD.cache() dataframe中的cache 利用catalog以表的形式对数据进行缓存 import org.apache.spark.SparkConf impo…...
Python中如何用栈实现队列
目录 一、引言 二、使用两个栈实现队列 三、性能分析 四、应用场景 五、代码示例 六、优缺点总结 一、引言 队列(Queue)和栈(Stack)是计算机科学中常用的数据结构。队列是一种特殊的线性表,只允许在表的前端进行…...
python模块pyDes,DES对称加密算法库
一、简介 pyDes是一个Python模块,用于进行DES(Data Encryption Standard)加密和解密操作。DES是一种对称密钥加密算法,广泛用于数据保密和传输。 优点: 1.简单易用:pyDes模块提供了简单的接口,…...
Centos7安装配置nginx
快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解(如有不正确的地方欢迎各位小伙伴在评论区提意见,小编会及时修改) Centos7安装配置nginx Nginx介绍 Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务,也…...
9.Spring 整合 Redis
引入依赖:spring-boot-starter-data-redis配置 Redis:配置数据库参数、编写配置类,构造 RedisTemplate访问 Redis: redisTemplate.opsForValue() redisTemplate.opsForHash() redisTemplate.opsForList() redisTemplate.opsForSe…...
【Java学习笔记】73 - 正则表达式
项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter27/src/com/yinhai/regexp 一、引入正则表达式 1.提取文章中所有的英文单词 2.提取文章中所有的数字 3.提取文章中所有的英文单词和数字 4.提取百度热榜标题 正则表达式是处理文本的利器…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
