【设计模式】工厂方法模式 在java中的应用
文章目录
- 1. 引言
- 工厂方法模式的定义
- 2. 工厂方法模式的核心概念
- 工厂方法模式的目的和原理
- 与其他创建型模式的比较(如简单工厂和抽象工厂)
- 3. Java中工厂方法模式的实现
- 基本的工厂方法模式结构
- 示例代码:创建不同类型的日志记录器
- 4. 工厂方法模式的应用场景
- 适用场景说明
- 真实世界的应用示例
- 5. 工厂方法模式的优点与缺点
- 优点分析
- 缺点分析
- 6. 相关设计模式的探讨
1. 引言
工厂方法模式的定义
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂方法模式中,创建对象的任务被交给了一个方法,这个方法通常被称为“工厂方法”。这种模式是通过让其子类决定应该实例化哪一个类来达到将对象创建的过程封装的目的,从而使得系统在不具体指定对象的类型的情况下工作。
工厂方法模式主要解决的问题是在编程环境中,当系统需要引入新的产品时,不需要修改已有的代码,只需要添加新的代码即可,从而增强了系统的可扩展性和可维护性。这种模式非常适合那些结构中存在大量具有相同接口的类的情况。
2. 工厂方法模式的核心概念
工厂方法模式的目的和原理
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂方法模式中,创建对象的任务被一个方法封装起来,而不是直接使用 new 关键字。这种模式是通过定义一个创建对象的接口来实现的,但由子类决定实例化哪一个类。工厂方法让类的实例化推迟到其子类。
工厂方法模式主要解决接口选择的问题。它达到了依赖倒置的原则,即“依赖于抽象而不依赖于具体”。使用工厂方法模式的主要目的是增加程序的灵活性和扩展性,同时隐藏具体类的实现细节,减少客户端与具体类之间的依赖。
与其他创建型模式的比较(如简单工厂和抽象工厂)
-
简单工厂模式:简单工厂模式不是一个真正的设计模式,但常被用于创建对象。在简单工厂里,一个工厂类根据传入的参数决定创建出哪一种产品类的实例。这种模式的缺点在于工厂类的职责相对过重,违背了高内聚责任分配原则,一旦需要添加新产品就不得不修改工厂逻辑,这违反了开放封闭原则。
-
抽象工厂模式:抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式通常用来生产产品族的产品。与工厂方法模式的主要区别在于,抽象工厂模式需要处理多个产品,这些产品一起构成了一个产品族。在抽象工厂模式中,每个工厂可以生产多种产品。
抽象工厂方法模式与简单工厂模式的区别主要在于,抽象工厂方法模式的工厂类通常有一个抽象层次,这使得在添加新产品时,只需要添加一个具体的工厂类和产品类,不需要修改已有的工厂和产品类代码,更好地符合开放封闭原则。而与抽象工厂模式相比,简单工厂方法模式在处理单一产品时更为简洁和专注。
3. Java中工厂方法模式的实现
基本的工厂方法模式结构
工厂方法模式主要涉及三个角色:
- 抽象产品(Product):定义了产品的接口,所有具体产品都需要实现这个接口。
- 具体产品(Concrete Product):实现或扩展抽象产品的接口。每个具体产品都对应一个特定的业务或处理逻辑。
- 抽象创建者(Creator):声明工厂方法,该方法返回一个抽象产品类型的对象。创建者类中也可以提供工厂方法的默认实现。
- 具体创建者(Concrete Creator):重写或实现抽象创建者中的工厂方法,以返回一个具体产品的实例。
示例代码:创建不同类型的日志记录器
在这个示例中,我们将定义一个日志记录器接口(抽象产品),具体的日志记录器(如文件日志记录器和控制台日志记录器),以及一个抽象的日志工厂,具体的日志工厂将根据需要创建相应类型的日志记录器。
// 抽象产品
public interface Logger {void log(String message);
}// 具体产品1
public class FileLogger implements Logger {@Overridepublic void log(String message) {System.out.println("Logging to a file: " + message);}
}// 具体产品2
public class ConsoleLogger implements Logger {@Overridepublic void log(String message) {System.out.println("Logging to console: " + message);}
}// 抽象创建者
public abstract class LoggerFactory {public abstract Logger createLogger();// 可以包含一些通用的逻辑public void logMessage(String message) {Logger logger = createLogger();logger.log(message);}
}// 具体创建者1
public class FileLoggerFactory extends LoggerFactory {@Overridepublic Logger createLogger() {// 可以包含创建具体产品的逻辑,例如处理与文件相关的配置return new FileLogger();}
}// 具体创建者2
public class ConsoleLoggerFactory extends LoggerFactory {@Overridepublic Logger createLogger() {return new ConsoleLogger();}
}// 使用示例
public class Demo {public static void main(String[] args) {LoggerFactory factory;Logger logger;// 使用文件日志记录器factory = new FileLoggerFactory();factory.logMessage("This is a file logger example.");// 使用控制台日志记录器factory = new ConsoleLoggerFactory();factory.logMessage("This is a console logger example.");}
}
在这个例子中,LoggerFactory 充当抽象创建者,FileLoggerFactory 和 ConsoleLoggerFactory 是具体的创建者,它们分别创建 FileLogger 和 ConsoleLogger 这两种具体产品。这样的设计允许系统在不直接依赖具体类的情况下增加或替换产品类。
4. 工厂方法模式的应用场景
适用场景说明
工厂方法模式特别适合以下几种情况:
- 创建对象的逻辑复杂:当创建一个对象的决策需要考虑多个因素时,将这些逻辑封装在一个单独的工厂方法中可以避免代码重复,并隐藏复杂的实现细节。
- 产品类层次结构:当产品类有多个等级结构时,工厂方法可以在不同层次中使用,每个具体工厂负责创建特定的产品对象。
- 扩展性要求高:当系统中产品类的种类经常变化,但是客户端仍然使用相同的接口时,工厂方法模式可以很容易地新增新的具体产品类而不需要修改现有代码。
- 解耦框架与实现:工厂方法可以在一个框架中用来封装和隔离具体实现,客户端代码可以通过工厂接口与具体实现解耦。
真实世界的应用示例
在Java标准库中,工厂方法模式的应用非常广泛。以下是一些典型的例子:
java.util.Calendar:Calendar.getInstance()是一个工厂方法,它根据当前的地理、政治环境返回不同的日历实现。java.util.ResourceBundle:ResourceBundle.getBundle()是一个工厂方法,用于根据不同的地区返回不同的资源束,以支持国际化。java.text.NumberFormat:NumberFormat.getInstance()提供了一个工厂方法,根据不同的地区返回不同的格式化对象,用于格式化数字。java.nio.charset.Charset:Charset.forName(String charsetName)方法是一个工厂方法,它根据名称返回不同的字符集对象。
这些例子展示了工厂方法模式如何在Java标准库中被用来提供一个统一的接口,同时允许灵活地根据不同的条件返回不同的实例,从而使得库的使用更加灵活和方便。
5. 工厂方法模式的优点与缺点
优点分析
- 增加系统的灵活性:工厂方法模式使得一个类的实例化延迟到其子类,因此在修改或扩展子类时不需要修改原有的代码,符合开闭原则。
- 促进解耦:客户代码从具体类解耦,仅依赖于产品接口。这使得客户代码更加稳定,不受具体实现的变动影响,提高了系统的可维护性。
- 扩展性强:新增一个产品类只需要添加一个具体的产品类和相应的工厂类,无需修改现有系统,易于扩展。
- 屏蔽产品类:产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口。这降低了系统的复杂度,提高了程序的可读性和可维护性。
缺点分析
- 类的数量增多:每增加一个产品,相应地也需要增加一个工厂类,这会导致系统中类的个数成倍增加,增加了系统的复杂度。
- 系统的抽象性增加:由于加入了工厂类,需要用户理解这种抽象的概念,并根据抽象来进行系统设计和编码,对初学者不够友好。
- 代码复杂度提高:相较于直接创建实例,使用工厂方法可能会使代码更加复杂或者增加设计上的难度。
总的来说,工厂方法模式在需要保持系统的灵活性和可扩展性时非常有用,尤其是在系统中有多个类的实例需要创建时。然而,这种模式也可能导致代码更加抽象,增加学习和维护的成本。开发者在选择使用工厂方法模式时应当考虑到这些权衡。
6. 相关设计模式的探讨
工厂方法模式是创建型设计模式的一种,但了解其他相关的设计模式可以帮助开发者更全面地理解设计模式在软件开发中的应用。以下是一些与工厂方法模式相关或互补的设计模式:
-
抽象工厂模式:与工厂方法模式类似,抽象工厂模式也用于创建一系列相关或依赖的对象。不同之处在于抽象工厂模式使用多个工厂方法来创建一系列产品,而不是只创建一种产品。
-
建造者模式:当创建复杂对象的算法应与对象的部件及其组装方式解耦时,建造者模式非常有用。这个模式允许你逐步创建复杂对象,使用不同的方法来构建对象的不同部分。
-
单例模式:当系统中需要确保一个类只有一个实例,并且需要一个全局访问点时,单例模式是非常有用的。虽然这不是直接创建对象的模式,但它管理创建和访问对象的方式。
-
原型模式:当创建一个对象的成本较高,且相似对象经常被请求时,原型模式可以克隆已存在的对象而不是新建。
相关文章:
【设计模式】工厂方法模式 在java中的应用
文章目录 1. 引言工厂方法模式的定义 2. 工厂方法模式的核心概念工厂方法模式的目的和原理与其他创建型模式的比较(如简单工厂和抽象工厂) 3. Java中工厂方法模式的实现基本的工厂方法模式结构示例代码:创建不同类型的日志记录器 4. 工厂方法…...
Pytest框架学习20--conftest.py
conftest.py作用 正常情况下,如果多个py文件之间需要共享数据,如一个变量,或者调用一个方法 需要先在一个新文件中编写函数等,然后在使用的文件中导入,然后使用 pytest中定义个conftest.py来实现数据,参…...
【面试开放题】挫折、问题、擅长、应用技能
1. 项目中遇到的最大挫折是什么?你是如何应对的? 解答思路: 这个问题通常考察你的问题解决能力、抗压能力和团队协作精神。回答时,可以从以下几个角度展开: 问题背景: 描述项目中遇到的具体挑战。是技术难…...
CTF-PWN: 全保护下格式化字符串利用 [第一届“吾杯”网络安全技能大赛 如果能重来] 赛后学习(没思路了)
通过网盘分享的文件:如果能重来.zip 链接: https://pan.baidu.com/s/1XKIJx32nWVcSpKiWFQGpYA?pwd1111 提取码: 1111 --来自百度网盘超级会员v2的分享漏洞分析 格式化字符串漏洞,在printf(format); __int64 sub_13D7() {char format[56]; // [rsp10h] [rbp-40h]…...
C++学习日记---第16天
笔记复习 1.C对象模型 在C中,类内的成员变量和成员函数分开存储 我们知道,C中的成员变量和成员函数均可分为两种,一种是普通的,一种是静态的,对于静态成员变量和静态成员函数,我们知道他们不属于类的对象…...
SOA、分布式、微服务之间的关系和区别?
在当今的软件开发领域,SOA(面向服务架构)、分布式系统和微服务是三个重要的概念。它们各自有着独特的特性和应用场景,同时也存在着密切的关系。以下是关于这三者之间关系和区别的详细分析: 关系 分布式架构的范畴&…...
java基础概念46-数据结构1
一、引入 List集合的三种实现类使用了不同的数据结构! 二、数据结构的定义 三、常见的数据结构 3-1、栈 特点:先进后出,后进先出。 java内存容器: 3-2、队列 特点:先进先出、后进后出。 栈VS队列-小结 3-3、数组 3-…...
Node.js-Mongodb数据库
MongoDB MongoDB是什么? MongoDB是一个基于分布式文件存储的数据库 数据库是什么? 数据库(DataBase)是按照数据结构来组织、存储和管理数据的应用程序(软件) 数据库作用? 对数据进行增、删…...
STM32 ADC --- 知识点总结
STM32 ADC — 知识点总结 文章目录 STM32 ADC --- 知识点总结cubeMX中配置注解单次转换模式、连续转换模式、扫描模式单通道采样的情况单次转换模式:连续转换模式: 多通道采样的情况禁止扫描模式(单次转换模式或连续转换模式)单次…...
技术创新与人才培养并重 软通动力子公司鸿湖万联亮相OpenHarmony人才生态大会
11月27日,由开放原子开源基金会指导,OpenHarmony项目群工作委员会主办的OpenHarmony人才生态大会2024在武汉隆重举办。软通动力子公司鸿湖万联作为OpenHarmony项目群A类捐赠人应邀出席。大会期间,鸿湖万联不仅深度参与了OpenHarmony人才生态年…...
兔子繁衍问题
7-2 兔子繁衍问题 分数 15 全屏浏览 切换布局 作者 徐镜春 单位 浙江大学 一对兔子,从出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假如兔子都不死,请问第1个月出生的一对兔子,至少需要繁衍到第几个月时兔…...
汉代风云人物 1晁错
晁错曾是汉景帝的老师。汉景帝登基后,晁错提出削藩建议,这一举措遭到诸多藩国诸侯的强烈反对,由此引发了紧张局势。 袁盎此前曾担任吴国的宰相,晁错觉得袁盎与吴国等藩国关系密切,很可能知晓藩王们谋反的相关情况却没…...
学习threejs,使用specularMap设置高光贴图
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.MeshPhongMaterial高…...
【UE5 C++】判断两点连线是否穿过球体
目录 前言 方法一 原理 代码 测试 结果 方法二 原理 一、检查连线与球体的相交情况 二、检查距离与球体半径的关系 三、检查连线与球体的相交 代码 前言 通过数学原理判断空间中任意两点的连线是否穿过球体,再通过射线检测检验算法的正确性。 方法一 …...
【Blender】如何创建空心管道
步骤 1:创建一个圆柱体 添加圆柱体: 在 Object Mode 下按 Shift A > Mesh > Cylinder。 步骤 2:制作空心效果 进入编辑模式: 选中圆柱体,按 Tab 进入 Edit Mode。 删除顶部和底部面: 按 3 进入面选…...
ChromeBook11 HP G7EE 刷入Ubuntu的记录
设置开发模式-> 拆电池(解锁)-> 刷入bios ->使用u盘刷入系统。 下面是详细过程,除了拆机有点紧,没有难度(我不负责~ 其实我试了好几次其他系统的,先进了pe,pe没问题(音频x),有一个win10的u盘(几个…...
16asm - 汇编介绍 和 debug使用
文章目录 前言硬件运行机制微机系统硬件组成计算机系统组成8086cpu组织架构dosbox安装配置debug debug使用R命令D命令E命令U命令T命令A命令标志寄存器 总结 前言 各位师傅大家好,我是qmx_07,今天给大家讲解 十六位汇编 和 debug调试器的使用 硬件运行…...
初识QT第一天
思维导图 利用Qt尝试做出原神登陆界面 import sys from PyQt6.QtGui import QIcon, QPixmap, QMovie from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QLineEdit# 封装原神窗口类 class Genshin(QWidget):# 构造函数def __init__(self):# 初始化父类…...
ChatGPT科研应用、论文写作、课题申报、数据分析与AI绘图
随着人工智能技术的飞速发展,ChatGPT等先进语言模型正深刻改变着科研工作的面貌。从科研灵感的激发、论文的高效撰写,到课题的成功申报,乃至复杂数据的深度分析与可视化呈现,AI技术均展现出前所未有的潜力。其实众多科研前沿工作者…...
原子类、AtomicLong、AtomicReference、AtomicIntegerFieldUpdater、LongAdder
原子类 JDK提供的原子类,即Atomic*类有很多,大体可做如下分类: 形式类别举例Atomic*基本类型原子类AtomicInteger、AtomicLong、AtomicBooleanAtomic*Array数组类型原子类AtomicIntegerArray、AtomicLongArray、AtomicReferenceArrayAtomic…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
