当前位置: 首页 > news >正文

【设计模式】工厂方法模式 在java中的应用

文章目录

      • 1. 引言
        • 工厂方法模式的定义
      • 2. 工厂方法模式的核心概念
        • 工厂方法模式的目的和原理
        • 与其他创建型模式的比较(如简单工厂和抽象工厂)
      • 3. Java中工厂方法模式的实现
        • 基本的工厂方法模式结构
        • 示例代码:创建不同类型的日志记录器
      • 4. 工厂方法模式的应用场景
        • 适用场景说明
        • 真实世界的应用示例
      • 5. 工厂方法模式的优点与缺点
        • 优点分析
        • 缺点分析
      • 6. 相关设计模式的探讨

1. 引言

工厂方法模式的定义

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂方法模式中,创建对象的任务被交给了一个方法,这个方法通常被称为“工厂方法”。这种模式是通过让其子类决定应该实例化哪一个类来达到将对象创建的过程封装的目的,从而使得系统在不具体指定对象的类型的情况下工作。

工厂方法模式主要解决的问题是在编程环境中,当系统需要引入新的产品时,不需要修改已有的代码,只需要添加新的代码即可,从而增强了系统的可扩展性和可维护性。这种模式非常适合那些结构中存在大量具有相同接口的类的情况。

2. 工厂方法模式的核心概念

工厂方法模式的目的和原理

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂方法模式中,创建对象的任务被一个方法封装起来,而不是直接使用 new 关键字。这种模式是通过定义一个创建对象的接口来实现的,但由子类决定实例化哪一个类。工厂方法让类的实例化推迟到其子类。

工厂方法模式主要解决接口选择的问题。它达到了依赖倒置的原则,即“依赖于抽象而不依赖于具体”。使用工厂方法模式的主要目的是增加程序的灵活性和扩展性,同时隐藏具体类的实现细节,减少客户端与具体类之间的依赖。

与其他创建型模式的比较(如简单工厂和抽象工厂)
  • 简单工厂模式:简单工厂模式不是一个真正的设计模式,但常被用于创建对象。在简单工厂里,一个工厂类根据传入的参数决定创建出哪一种产品类的实例。这种模式的缺点在于工厂类的职责相对过重,违背了高内聚责任分配原则,一旦需要添加新产品就不得不修改工厂逻辑,这违反了开放封闭原则。

  • 抽象工厂模式:抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式通常用来生产产品族的产品。与工厂方法模式的主要区别在于,抽象工厂模式需要处理多个产品,这些产品一起构成了一个产品族。在抽象工厂模式中,每个工厂可以生产多种产品。

抽象工厂方法模式与简单工厂模式的区别主要在于,抽象工厂方法模式的工厂类通常有一个抽象层次,这使得在添加新产品时,只需要添加一个具体的工厂类和产品类,不需要修改已有的工厂和产品类代码,更好地符合开放封闭原则。而与抽象工厂模式相比,简单工厂方法模式在处理单一产品时更为简洁和专注。

3. Java中工厂方法模式的实现

基本的工厂方法模式结构

工厂方法模式主要涉及三个角色:

  1. 抽象产品(Product):定义了产品的接口,所有具体产品都需要实现这个接口。
  2. 具体产品(Concrete Product):实现或扩展抽象产品的接口。每个具体产品都对应一个特定的业务或处理逻辑。
  3. 抽象创建者(Creator):声明工厂方法,该方法返回一个抽象产品类型的对象。创建者类中也可以提供工厂方法的默认实现。
  4. 具体创建者(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 充当抽象创建者,FileLoggerFactoryConsoleLoggerFactory 是具体的创建者,它们分别创建 FileLoggerConsoleLogger 这两种具体产品。这样的设计允许系统在不直接依赖具体类的情况下增加或替换产品类。

4. 工厂方法模式的应用场景

适用场景说明

工厂方法模式特别适合以下几种情况:

  1. 创建对象的逻辑复杂:当创建一个对象的决策需要考虑多个因素时,将这些逻辑封装在一个单独的工厂方法中可以避免代码重复,并隐藏复杂的实现细节。
  2. 产品类层次结构:当产品类有多个等级结构时,工厂方法可以在不同层次中使用,每个具体工厂负责创建特定的产品对象。
  3. 扩展性要求高:当系统中产品类的种类经常变化,但是客户端仍然使用相同的接口时,工厂方法模式可以很容易地新增新的具体产品类而不需要修改现有代码。
  4. 解耦框架与实现:工厂方法可以在一个框架中用来封装和隔离具体实现,客户端代码可以通过工厂接口与具体实现解耦。
真实世界的应用示例

在Java标准库中,工厂方法模式的应用非常广泛。以下是一些典型的例子:

  1. java.util.CalendarCalendar.getInstance()是一个工厂方法,它根据当前的地理、政治环境返回不同的日历实现。
  2. java.util.ResourceBundleResourceBundle.getBundle()是一个工厂方法,用于根据不同的地区返回不同的资源束,以支持国际化。
  3. java.text.NumberFormatNumberFormat.getInstance()提供了一个工厂方法,根据不同的地区返回不同的格式化对象,用于格式化数字。
  4. java.nio.charset.CharsetCharset.forName(String charsetName)方法是一个工厂方法,它根据名称返回不同的字符集对象。

这些例子展示了工厂方法模式如何在Java标准库中被用来提供一个统一的接口,同时允许灵活地根据不同的条件返回不同的实例,从而使得库的使用更加灵活和方便。

5. 工厂方法模式的优点与缺点

优点分析
  1. 增加系统的灵活性:工厂方法模式使得一个类的实例化延迟到其子类,因此在修改或扩展子类时不需要修改原有的代码,符合开闭原则。
  2. 促进解耦:客户代码从具体类解耦,仅依赖于产品接口。这使得客户代码更加稳定,不受具体实现的变动影响,提高了系统的可维护性。
  3. 扩展性强:新增一个产品类只需要添加一个具体的产品类和相应的工厂类,无需修改现有系统,易于扩展。
  4. 屏蔽产品类:产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口。这降低了系统的复杂度,提高了程序的可读性和可维护性。
缺点分析
  1. 类的数量增多:每增加一个产品,相应地也需要增加一个工厂类,这会导致系统中类的个数成倍增加,增加了系统的复杂度。
  2. 系统的抽象性增加:由于加入了工厂类,需要用户理解这种抽象的概念,并根据抽象来进行系统设计和编码,对初学者不够友好。
  3. 代码复杂度提高:相较于直接创建实例,使用工厂方法可能会使代码更加复杂或者增加设计上的难度。

总的来说,工厂方法模式在需要保持系统的灵活性和可扩展性时非常有用,尤其是在系统中有多个类的实例需要创建时。然而,这种模式也可能导致代码更加抽象,增加学习和维护的成本。开发者在选择使用工厂方法模式时应当考虑到这些权衡。

6. 相关设计模式的探讨

工厂方法模式是创建型设计模式的一种,但了解其他相关的设计模式可以帮助开发者更全面地理解设计模式在软件开发中的应用。以下是一些与工厂方法模式相关或互补的设计模式:

  1. 抽象工厂模式:与工厂方法模式类似,抽象工厂模式也用于创建一系列相关或依赖的对象。不同之处在于抽象工厂模式使用多个工厂方法来创建一系列产品,而不是只创建一种产品。

  2. 建造者模式:当创建复杂对象的算法应与对象的部件及其组装方式解耦时,建造者模式非常有用。这个模式允许你逐步创建复杂对象,使用不同的方法来构建对象的不同部分。

  3. 单例模式:当系统中需要确保一个类只有一个实例,并且需要一个全局访问点时,单例模式是非常有用的。虽然这不是直接创建对象的模式,但它管理创建和访问对象的方式。

  4. 原型模式:当创建一个对象的成本较高,且相似对象经常被请求时,原型模式可以克隆已存在的对象而不是新建。

相关文章:

【设计模式】工厂方法模式 在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…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM&#xff09…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

GitHub 趋势日报 (2025年06月06日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...