Java二十三种设计模式-工厂方法模式(2/23)
工厂方法模式:设计模式中的瑞士军刀
引言
在软件开发中,工厂方法模式是一种常用的创建型设计模式,它用于处理对象的创建,将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程,还提高了代码的可维护性和可扩展性。
基础知识,java设计模式总体来说设计模式分为三大类:
(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
第一部分:工厂方法模式概述
1.1 工厂方法模式定义
工厂方法模式是一种创建型设计模式,用于将对象的创建过程封装在具体的工厂类中,而不是在客户端代码中直接创建。这种模式的目的是将对象创建的逻辑和使用逻辑分离,从而提高代码的可维护性和灵活性。
基本定义
工厂方法模式定义了一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method让类的实例化推迟到子类进行。
与简单工厂模式的区别
简单工厂模式使用一个中心化的工厂类来创建所有的对象,客户端代码直接与这个工厂类交互以获取所需的对象。这种方式虽然可以简化对象的创建过程,但随着产品种类的增加,工厂类的责任会变得越来越重,难以维护,且违反了开闭原则(对扩展开放,对修改封闭)。
工厂方法模式通过定义一个创建对象的接口,让具体的工厂类实现这个接口,从而为每个产品提供一个具体的工厂,这样新增产品种类时,只需要增加一个具体的工厂类,不需要修改已有代码,更好地遵循了开闭原则。
1.2 工厂方法模式组成
抽象产品(Product)
抽象产品是产品类的共同父类,定义了产品的接口。它是一个抽象角色,不实现具体的产品类。
具体产品(Concrete Product)
具体产品是抽象产品的子类,实现了抽象产品接口中定义的方法。在工厂方法模式中,具体产品由具体工厂类创建。
抽象工厂(Creator)
抽象工厂定义了创建对象的接口。它是一个抽象角色,不实现具体的创建方法。
具体工厂(Concrete Creator)
具体工厂是抽象工厂的子类,实现了抽象工厂中的创建方法。它负责实例化具体产品。
客户端(Client)
客户端代码使用抽象工厂来请求创建对象,客户端不直接与具体产品或具体工厂交互,而是通过抽象工厂与具体工厂进行交互。
通过这种分离,工厂方法模式提供了一种灵活的方式来管理对象的创建,使得新增产品种类时,不需要修改已有的客户端代码,只需要增加相应的具体工厂类即可。这种模式在实际开发中非常实用,尤其是在产品种类较多且经常变化的情况下。在下一部分中,我们将通过Java代码示例来展示工厂方法模式的具体实现。
第二部分:工厂方法模式实现
2.1 Java实现示例
以下是使用Java语言实现工厂方法模式的一个简单示例。我们将创建一个用于生成不同类型汽车的工厂。
// 抽象产品:汽车
interface Car {void assemble();
}// 具体产品:运动型汽车
class SportsCar implements Car {public void assemble() {System.out.println("Assembling a Sports Car.");}
}// 具体产品:豪华型汽车
class LuxuryCar implements Car {public void assemble() {System.out.println("Assembling a Luxury Car.");}
}// 抽象工厂:汽车工厂
interface CarFactory {Car createCar();
}// 具体工厂:运动型汽车工厂
class SportsCarFactory implements CarFactory {public Car createCar() {return new SportsCar();}
}// 具体工厂:豪华型汽车工厂
class LuxuryCarFactory implements CarFactory {public Car createCar() {return new LuxuryCar();}
}// 客户端代码
public class Client {public static void main(String[] args) {CarFactory factory = null;// 根据需求选择不同类型的汽车工厂factory = new SportsCarFactory();Car car = factory.createCar();car.assemble();factory = new LuxuryCarFactory();car = factory.createCar();car.assemble();}
}
2.2 模式中的角色和职责
抽象产品(Product)
- 职责:定义一个产品接口,规范具体产品类应实现的行为。
具体产品(Concrete Product)
- 职责:实现抽象产品接口的具体类,是工厂方法模式中被创建的对象。
抽象工厂(Creator)
- 职责:声明一个创建产品的接口,不涉及具体类实例化。
具体工厂(Concrete Creator)
- 职责:
- 实现抽象工厂的接口。
- 具体实现创建产品的方法,生成具体产品对象。
客户端(Client)
- 职责:
- 根据需求选择相应的具体工厂。
- 通过具体工厂间接使用具体产品,实现了解耦。
在工厂方法模式中,客户端不直接与具体产品或具体工厂类交互,而是通过抽象工厂接口与具体工厂进行交互。这样做的好处是,当需要添加新的产品时,只需增加相应的具体工厂和具体产品类,而无需修改已有的客户端代码,从而遵循了开闭原则。这种模式提高了系统的灵活性和可扩展性,使得维护和扩展变得更加容易。在下一部分中,我们将讨论工厂方法模式的使用场景。
第三部分:工厂方法模式使用场景
3.1 产品族的扩展
当系统中存在一个产品族,且需要对产品族中的每个具体产品进行扩展时,工厂方法模式提供了一种非常合适的解决方案。
- 产品族:指一组具有相同接口的产品,这些产品通常在功能上有一定的相似性,但又存在一些差异。
- 应用场景:例如,在一个图形界面库中,可能存在多种不同类型的按钮(如圆形按钮、矩形按钮、带图标的按钮等)。这些按钮都属于按钮产品族,它们都实现了同一个按钮接口,但又各自有不同的实现。
工厂方法模式的应用:
- 通过定义一个抽象工厂和工厂方法,可以为每个具体的产品提供一个对应的具体工厂。
- 当需要扩展产品族时,只需增加相应的具体产品类和对应的具体工厂类,无需修改现有的工厂接口或其他工厂类。
3.2 依赖倒置原则
依赖倒置原则是面向对象设计原则之一,它要求高层模块不应依赖于低层模块,两者都应该依赖于抽象。
- 实现方式:工厂方法模式通过使用抽象产品和抽象工厂,使得客户端代码依赖于抽象而不是具体实现。
- 好处:这有助于降低模块间的耦合度,提高系统的灵活性和可维护性。
第四部分:工厂方法模式的优点与缺点
4.1 优点
封装性
工厂方法模式隐藏了对象创建的具体细节,客户端不需要知道具体是如何创建对象的。
扩展性
当需要添加新的产品时,只需增加相应的具体产品和工厂类,无需修改现有代码。
代码复用
通过使用工厂方法模式,可以在一个工厂类中创建多个相似对象,提高代码复用性。
4.2 缺点
增加系统复杂度
每增加一个产品类别,都需要增加一个具体类和产品类,这可能会导致系统中类的数量急剧增加。
增加系统的抽象性
在添加新的产品类时,需要对工厂方法的接口进行扩展,这可能会导致工厂方法的接口经常变化,增加了系统的抽象性。
不容易维护
当工厂方法模式的类数量逐渐增多时,可能会使系统难以理解和维护。
通过深入分析工厂方法模式的使用场景、优点和缺点,我们可以更明智地决定何时以及如何使用工厂方法模式。在实际开发中,我们应该根据具体需求和上下文来选择最合适的设计模式。在下一部分中,我们将比较工厂方法模式与其他设计模式,并提供一些最佳实践和建议。
第五部分:工厂方法模式与其他模式的比较
5.1 与抽象工厂模式的比较
工厂方法模式
- 定义:用于创建一系列相关或依赖对象的接口,而不需要指定具体类。
- 使用场景:当一个类不知道它所必须创建的对象的类时。
抽象工厂模式
- 定义:创建一个工厂接口,用于创建一系列相关的或依赖的抽象产品。
- 使用场景:当需要创建的产品族是相互关联的,并且希望它们能够一起被使用时。
不同点
- 产品种类:工厂方法模式创建一个产品,而抽象工厂模式创建产品族。
- 复杂性:抽象工厂模式通常比工厂方法模式复杂,因为它需要定义更多的接口和类。
5.2 与建造者模式的比较
工厂方法模式
- 关注点:对象的创建,隐藏创建逻辑。
- 适用情况:当创建过程只需要一个简单的步骤即可完成时。
建造者模式
- 关注点:构建一个复杂对象,同时允许用户只通过指定复杂对象的类型和内容就能构建它们。
- 适用情况:当创建过程需要多步骤或条件逻辑时。
差异
- 复杂性:建造者模式适用于创建更复杂的对象,而工厂方法模式适用于简单的创建过程。
- 灵活性:建造者模式提供了更多的灵活性,允许逐步构建对象。
第六部分:最佳实践和建议
6.1 使用工厂方法模式的最佳时机
- 产品族扩展:当需要创建的产品属于同一类别,并且可能需要扩展时。
- 依赖关系:当客户端不应该知道具体的产品类时,通过工厂方法模式可以降低客户端与具体产品的耦合。
6.2 避免滥用工厂方法模式
- 过度使用:避免在不需要对象创建逻辑封装的情况下使用工厂方法模式,这可能导致不必要的复杂性。
- 难以维护:随着产品种类的增加,管理大量的工厂类可能会变得困难。
6.3 替代方案
原型模式
- 定义:使用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。
- 适用场景:当创建新对象的成本较高时,或者需要通过复制现有的对象来快速创建新对象时。
依赖注入
- 定义:通过外部注入依赖对象,而不是在类内部创建。
- 好处:提高了代码的可测试性和灵活性。
服务定位器模式
- 定义:当需要访问一个服务时,客户端会查询服务定位器以获取服务实例。
- 适用场景:当系统中有大量的服务需要被访问,并且服务实例的创建和管理较为复杂时。
通过比较工厂方法模式与其他设计模式,我们可以更清晰地了解每种模式的适用场景和特点。在实际开发中,选择最合适的设计模式对于构建一个灵活、可维护的系统至关重要。同时,了解工厂方法模式的最佳实践和替代方案,可以帮助我们更好地应对不同的开发挑战。
结语
工厂方法模式是一种强大且灵活的设计模式,适用于多种不同的软件开发场景。通过本文的深入分析,希望读者能够对工厂方法模式有更全面的理解,并在实际开发中做出合理的设计选择。
相关文章:
Java二十三种设计模式-工厂方法模式(2/23)
工厂方法模式:设计模式中的瑞士军刀 引言 在软件开发中,工厂方法模式是一种常用的创建型设计模式,它用于处理对象的创建,将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程,还提高了代码的可维护性…...
【iOS】OC类与对象的本质分析
目录 前言clang常用命令对象本质探索属性的本质对象的内存大小isa 指针探究 前言 OC 代码的底层实现都是 C/C代码,OC 的对象都是基于 C/C 的数据结构实现的,实际 OC 对象的本质就是结构体,那到底是一个怎样的结构体呢? clang常用…...
【机器学习】使用Python的dlib库实现人脸识别技术
🔥 个人主页:空白诗 文章目录 一、引言二、传统人脸识别技术1. 基于几何特征的方法2. 基于模板匹配的方法3. 基于统计学习的方法 三、深度学习在脸识别中的应用1. 卷积神经网络(CNN)2. FaceNet和ArcFace 四、使用Python和dlib库实…...
GitHub 令牌泄漏, Python 核心资源库面临潜在攻击
TheHackerNews网站消息,软件供应链安全公司 JFrog 的网络安全研究人员称,他们发现了一个意外泄露的 GitHub 令牌,可授予 Python 语言 GitHub 存储库、Python 软件包索引(PyPI)和 Python 软件基金会(PSF&…...
【面试题】Golang 锁的相关问题(第七篇)
目录 1.Mutex 几种状态 1. 锁定状态(Locked) 2. 未锁定状态(Unlocked) 3. 唤醒状态(Woken) 4. 饥饿状态(Starving) 5. 等待者计数(Waiters Count) 总结…...
深入剖析CommonJS modules和ECMAScript modules
目录 前言CommonJS:服务器端模块化的先驱背景与起源语法与机制 ECMAScript Modules:现代前端的基石背景与起源语法与机制 比较与权衡语法差异加载机制编译时与运行时运行时行为构建第三方库现代开发环境 结论 前言 在 JavaScript 生态系统中,…...
角点检测及MATLAB实现
一、角点简介 角点通常指的是两条直线构成角时的交点。在更广泛的应用中,角点这一概念也被扩展到数字图像处理领域,其中角点被定义为图像中物体轮廓线的连接点,这些点在某方面属性特别突出,即在某些属性上强度最大或者最…...
TypeScript导学:从零开始
引言 TypeScript的背景 TypeScript是一种由微软开发的开源编程语言,它是JavaScript的一个超集,添加了可选的静态类型和基于类的面向对象编程。自2012年首次发布以来,TypeScript因其能够提高代码的可读性、可维护性和可扩展性而迅速获得了广…...
【BUG】已解决:IndexError: list index out of range
已解决:IndexError: list index out of range 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰,211科班出身,就职于医疗科技公司,热衷分享知识,武汉城市开发者社区主…...
AWS-S3实现Minio分片上传、断点续传、秒传、分片下载、暂停下载
文章目录 前言一、功能展示上传功能点下载功能点效果展示 二、思路流程上传流程下载流程 三、代码示例四、疑问 前言 Amazon Simple Storage Service(S3),简单存储服务,是一个公开的云存储服务。Web应用程序开发人员可以使用它存…...
Selenium - 设置元素等待及加载策略
7月18日资源分享: 耿直哥三部曲全——机器学习,强化学习,深度学习 链接: https://pan.baidu.com/s/1c_eVVeqCZmB6zszHt6ZXiw?pwdtf2a 在使用Selenium进行网页自动化测试时,一个常见的问题是页面加载速度和元素的可见性问题。…...
【数据结构】线性结构——数组、链表、栈和队列
目录 前言 一、数组(Array) 1.1优点 1.2缺点 1.3适用场景 二、链表(Linked List) 2.1优点 2.2缺点 2.3适用场景 三、栈(Stack) 3.1优点 3.2缺点 3.3适用场景 四、队列(Queue) 4.1优点…...
json将列表字典等转字符串,然后解析又转回来
在 Python 中使用 json 模块来方便地在数据和 JSON 格式字符串之间进行转换,以便进行数据的存储、传输或与其他支持 JSON 格式的系统进行交互。 JSON 字符串通过 json.loads() 函数转换为 Python 对象。 pthon对象通过json.dumps()转为字符串 import jsonstr_list…...
记录|.NET上位机开发和PLC通信的实现
本文记录源自:B站视频 实验结果:跟视频做下来是没有问题的。能运行。 自己补充做了视频中未实现的读取和写入数据部分【欢迎小伙伴指正不对的地方】 目录 前言一、项目Step1. 创建项目Step2. 创建动态图片展示Step3. 创建图片型按钮Step4. 创建下拉框Ste…...
微服务实战系列之玩转Docker(二)
前言 上一篇,博主对Docker的背景、理念和实现路径进行了简单的阐述。作为云原生技术的核心之一,轻量级的容器Docker,受到业界追捧。因为它抛弃了笨重的OS,也不带Data,可以说,能够留下来的都是打仗的“精锐…...
Linux:信号的概念与产生
信号概念 信号是进程之间事件异步通知的一种方式 在Linux命令行中,我们可以通过ctrl c来终止一个前台运行的进程,其实这就是一个发送信号的行为。我们按下ctrl c是在shell进程中,而被终止的进程,是在前台运行的另外一个进程。因…...
云监控(华为) | 实训学习day2(10)
spring boot基于框架的实现 简单应用 - 用户数据显示 开发步骤 第一步:文件-----》新建---项目 第二步:弹出的对话框中,左侧选择maven,右侧不选任何内容. 第三步,选择maven后,下一步 第4步 :出现对话框中填写项目名称 第5步&…...
数据结构第35节 性能优化 算法的选择
算法的选择对于优化程序性能至关重要。不同的算法在时间复杂度、空间复杂度以及适用场景上有着明显的差异。下面我将结合具体的代码示例,来讲解几种常见的算法选择及其优化方法。 示例 1: 排序算法 场景描述: 假设我们需要对一个整数数组进行排序。 算法选择: …...
每天一个数据分析题(四百三十六)- 正态分布
X为服从正态分布的随机变量N(2, 9), 如果P(X>c)P(X<c), 则c的值为() A. 3 B. 2 C. 9 D. 2/3 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python,SQL&…...
跟我学C++中级篇——虚函数的性能
一、虚函数性能 一般来说,面向对象的设计中,继承和多态是其中两个非常重要的特征。从使用的过程来看,一般应用到继承的,使用多态的可能性就非常大。而多态的实现有很多种, 但开发者通常认为的多态(动多态&…...
trl - 微调、对齐大模型的全栈工具
文章目录 一、关于 TRL亮点 二、安装1、Python包2、从源码安装3、存储库 三、命令行界面(CLI)四、如何使用1、SFTTrainer2、RewardTrainer3、PPOTrainer4、DPOTrainer 五、其它开发 & 贡献参考文献最近策略优化 PPO直接偏好优化 DPO 一、关于 TRL T…...
GuLi商城-商品服务-API-品牌管理-品牌分类关联与级联更新
先配置mybatis分页: 品牌管理增加模糊查询: 品牌管理关联分类: 一个品牌可以有多个分类 一个分类也可以有多个品牌 多对多的关系,用中间表 涉及的类: 方法都比较简单,就不贴代码了...
【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会
【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会 【创作不易,求点赞关注收藏】 文章目录 【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会一、版本情况介绍二、安装cuda1、到官网…...
在 Apifox 中如何高效批量添加接口请求 Body 参数?
在使用 Apifox 进行 API 设计时,你可能会遇到需要添加大量请求参数的情况。想象一下,如果一个接口需要几十甚至上百个参数,若要在接口的「修改文档」里一个个手动添加这些参数,那未免也太麻烦了,耗时且易出错。这时候&…...
专业PDF编辑工具:Acrobat Pro DC 2024.002.20933绿色版,提升你的工作效率!
软件介绍 Adobe Acrobat Pro DC 2024绿色便携版是一款功能强大的PDF编辑和转换软件,由Adobe公司推出。它是Acrobat XI系列的后续产品,提供了全新的用户界面和增强功能。用户可以借助这款软件将纸质文件转换为可编辑的电子文件,便于传输、签署…...
车载音视频App框架设计
简介 统一播放器提供媒体播放一致性的交互和视觉体验,减少各个媒体应用和场景独自开发的重复工作量,实现媒体播放链路的一致性,减少碎片化的Bug。本文面向应用开发者介绍如何快速接入媒体播放器。 主要功能: 新设计的统一播放U…...
StarRocks on AWS Graviton3,实现 50% 以上性价比提升
在数据时代,企业拥有前所未有的大量数据资产,但如何从海量数据中发掘价值成为挑战。数据分析凭借强大的分析能力,可从不同维度挖掘数据中蕴含的见解和规律,为企业战略决策提供依据。数据分析在营销、风险管控、产品优化等领域发挥…...
VUE中setup()
在Vue中,setup() 函数是Vue 3.0及更高版本引入的一个重要特性,它是Composition API的入口点。setup() 函数用于初始化组件的状态和逻辑,包括定义响应式数据、方法和生命周期钩子。以下是关于setup() 函数的详细解释: 1. 作用与特…...
【单元测试】SpringBoot
【单元测试】SpringBoot 1. 为什么单元测试很重要?‼️ 从前,有一个名叫小明的程序员,他非常聪明,但有一个致命的缺点:懒惰。小明的代码写得又快又好,但他总觉得单元测试是一件麻烦事,觉得代码…...
分布式搜索引擎ES-elasticsearch入门
1.分布式搜索引擎:luceneVS Solr VS Elasticsearch 什么是分布式搜索引擎 搜索引擎:数据源:数据库或者爬虫资源 分布式存储与搜索:多个节点组成的服务,提高扩展性(扩展成集群) 使用搜索引擎为搜索提供服务。可以从海量…...
做网站都需要什么资料/怎么找平台推广自己的产品
1 http://www.cnblogs.com/franksunny/archive/2011/11/17/2252926.html 2 http://www.cnblogs.com/vir56k/archive/2012/10/24/2737119.html 3 http://blog.30c.org/2798.html...
廊坊做网站电话/seo关键词优化外包
问题描述:父组件传如lesser和larger两个参数,并且是ajax从服务器获取的。子组件定义created阶段输出lesser和larger。但larger为空。改成延迟输出则正确。问题来源:https://segmentfault.com/q/1010000008912491提问者的主要问题是没有搞清楚…...
wordpress 打断点/百度大数据预测平台
C#的Garbage Collector(GC,垃圾回收器)往往让很多程序员产生了对于程序中使用的内存撒手不管的态度。他们会认为既然已经有GC在后台运行了,代码中就不需要多加注意了。事实上GC可以是最好的朋友,也可以是最坏的敌人,完全取决于代码。 ★垃圾…...
商城网站建设计划书/全国免费发布广告信息平台
《.net, 哥已心灰意冷》,这位哥哥说了那么多,其实也没有能证明他所面对的问题是.net带来的。 其实,每一段时间都有人讨论这个问题,有些人是真的讨论了.net和java之类的技术上的差别,但是我发觉人们关心的并…...
网站建设容易吗/百度竞价seo排名
点击上方“程序员小灰”,选择“置顶公众号” 有趣有内涵的文章第一时间送达! 上一次送书活动刚刚完结,有9位幸运的小伙伴得到了想要的图书,但是更多的读者们并没有获奖。 不过大家不必遗憾,慷慨的博文视点再次赞助了10…...
简网 互联 专业wordpress主机/媒体公关
C语言 _ 编辑、调试工具一、GCC编译器1、GNU工具2、GCC简介3、GCC编译器的版本4、gcc所支持后缀名解释5、编译器的主要组件6、GCC的基本用法和选项7、GCC的错误类型及对策8、**GCC编译过程**条件编译二、GDB调试工具1、Gdb调试流程:2、进入代码调试模式后一、GCC编译…...