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

Java设计模式-抽象工厂模式-一次性理解透

抽象工厂模式示意图

1. 抽象工厂模式简介

抽象工厂设计模式是创建型模式之一。抽象工厂模式与工厂模式几乎相似,只是它更像工厂中的工厂

如果您熟悉Java 中的工厂设计模式,或看过上一篇我写的“java简单工厂模式”,您会注意到我们有一个工厂类。此工厂类根据提供的输入返回不同的子类工厂类使用 if-else 或 switch 语句来实现这一点

但是在抽象工厂模式中,我们摆脱了 if-else 块,并为每个子类设置了一个工厂类。然后是一个抽象工厂类,它将根据输入的工厂类返回子类。起初,这似乎令人困惑,但一旦您看到实现,就很容易掌握和理解工厂和抽象工厂模式之间的细微差别。就像我们的工厂模式帖子一样,我们将使用相同的超类和子类。

2. 抽象工厂模式的原理

在这里插入图片描述
抽象工厂模式的角色包括:‌

  1. 抽象产品:‌定义了产品的规范和接口。‌
  2. 具体产品:‌实现了抽象产品的接口,‌是实际的产品对象。‌
  3. 抽象工厂:‌提供了创建产品的接口,‌但不负责实现这些接口。‌

抽象工厂模式通过提供一个创建一系列相关或相互依赖对象的接口,‌而无需指定它们具体的类,‌实现了产品的创建与使用的分离。‌这种模式特别适用于那些需要创建多个相关产品对象的场景,‌如组装电脑时选择CPU、‌硬盘、‌内存等配件,‌或者创建一个包含多种类型产品的产品族,‌如手机和电脑等电子产品。‌通过抽象工厂模式,‌可以更好地管理这些产品的创建和组合,‌提高系统的可维护性和可扩展性。‌

3. 抽象工厂的使用场景

下面,整理出了4中典型的关于“抽象工厂模式”的使用场景介绍。

3.1 系统独立于产品创建、‌组合和表示

当系统需要独立于其产品的创建、‌组合和表示时,‌抽象工厂模式可以提供一个统一的接口来创建一系列相关的产品对象,‌而不必关心具体的实现细节。‌

3.2 多个产品系列配置

如果一个系统需要由多个产品系列中的一个来配置,‌抽象工厂模式可以提供一个统一的接口来创建这些产品系列中的对象,‌确保系统的一致性和可维护性。‌

3.3 强调一系列相关的产品对象设计

当需要强调一系列相关的产品对象的设计以便进行联合使用时,‌抽象工厂模式可以确保这些对象一起被正确地创建和使用,‌以满足特定的功能需求。‌

3.4 提供产品类库的接口而非实现:

如果提供一个产品类库,‌而只想显示它们的接口而不是实现时,‌抽象工厂模式可以通过提供一个统一的接口来创建这些产品对象,‌使得客户端代码不依赖于具体的实现细节,‌增加了系统的灵活性和可扩展性。‌

4. 抽象工厂的代码示例介绍

在这里插入图片描述
我们将针对此图进行编程,着重介绍抽象工厂模式。

4.1 抽象工厂设计模式超类和子类

4.1.1 Computer.java

public abstract class Computer {public abstract String getRAM();public abstract String getHDD();public abstract String getCPU();@Overridepublic String toString(){return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();}
}

4.1.2 PC.java

public class PC extends Computer {private String ram;private String hdd;private String cpu;public PC(String ram, String hdd, String cpu){this.ram=ram;this.hdd=hdd;this.cpu=cpu;}@Overridepublic String getRAM() {return this.ram;}@Overridepublic String getHDD() {return this.hdd;}@Overridepublic String getCPU() {return this.cpu;}}

4.1.3 Server.java

public class Server extends Computer {private String ram;private String hdd;private String cpu;public Server(String ram, String hdd, String cpu){this.ram=ram;this.hdd=hdd;this.cpu=cpu;}@Overridepublic String getRAM() {return this.ram;}@Overridepublic String getHDD() {return this.hdd;}@Overridepublic String getCPU() {return this.cpu;}}

4.2 编写每个子类的工厂类

首先我们需要创建一个抽象工厂接口或抽象类,如上图这个抽象给抽象工厂类叫ComputerAbstractFactory.java

public interface ComputerAbstractFactory {public Computer createComputer();
}

注意该createComputer()方法返回的是超类的一个实例Computer。现在我们的工厂类将实现此接口并返回各自的子类。

4.2.1 PCFactory.java

public class PCFactory implements ComputerAbstractFactory {private String ram;private String hdd;private String cpu;public PCFactory(String ram, String hdd, String cpu){this.ram=ram;this.hdd=hdd;this.cpu=cpu;}@Overridepublic Computer createComputer() {return new PC(ram,hdd,cpu);}
}

类似地,我们将有一个用于Server子类的工厂类。ServerFactory.java

4.2.2 ServerFactory.java

public class ServerFactory implements ComputerAbstractFactory {private String ram;private String hdd;private String cpu;public ServerFactory(String ram, String hdd, String cpu){this.ram=ram;this.hdd=hdd;this.cpu=cpu;}@Overridepublic Computer createComputer() {return new Server(ram,hdd,cpu);}
}

现在我们将创建一个消费者类,为客户端类创建子类提供入口点。ComputerFactory.java

public class ComputerFactory {public static Computer getComputer(ComputerAbstractFactory factory){return factory.createComputer();}
}

注意,它是一个简单的类,getComputer方法接受ComputerAbstractFactory参数并返回Computer对象。此时实现应该已经很清晰了。

让我们编写一个简单的测试方法,看看如何使用抽象工厂来获取子类的实例。TestDesignPatterns.java

public class TestDesignPatterns {public static void main(String[] args) {testAbstractFactory();}private static void testAbstractFactory() {Computer pc = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new PCFactory("2 GB","500 GB","2.4 GHz"));Computer server = com.journaldev.design.abstractfactory.ComputerFactory.getComputer(new ServerFactory("16 GB","1 TB","2.9 GHz"));System.out.println("AbstractFactory PC Config::"+pc);System.out.println("AbstractFactory Server Config::"+server);}
}

上述程序的输出将是:

AbstractFactory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz
AbstractFactory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

5. 抽象工厂模式优缺点

抽象工厂模式的优点包括封装性解耦性、‌产品族一致性、‌易于替换扩展、‌提高系统灵活性,‌而缺点则包括复杂性增加、‌不易于新增产品、‌不支持单一产品的变化。‌

5.1 抽象工厂模式优点

5.1.1 封装性和解耦性:

抽象工厂模式将对象的创建和使用分离,‌客户端代码不需要关心具体的产品类,‌从而实现了解耦。‌客户端代码只需要依赖抽象工厂接口,‌而不依赖具体产品。‌

5.1.2 产品族一致性

抽象工厂模式确保一组相关或依赖的产品能够协同工作,‌因为每个具体工厂类都会创建一整套相关产品。‌这有助于保持产品之间的一致性。‌

5.1.3 易于替换和扩展

通过添加新的具体工厂类和产品类,‌可以轻松扩展抽象工厂模式,‌而不需要修改现有的客户端代码。‌这使得系统更易于维护和扩展。‌

5.1.4 提高系统灵活性

抽象工厂模式允许在运行时切换不同的具体工厂,‌从而使应用程序更容易适应不同的配置或环境,‌提高了系统的灵活性。‌

5.2 抽象工厂模式缺点

5.2.1 复杂性增加:

抽象工厂模式引入了多个抽象类和接口,‌以及多个具体工厂和产品类,‌因此可能会增加系统的复杂性。‌对于小规模应用程序或简单的需求,‌可能显得过于繁琐。‌

5.2.2 不易于新增产品

如果需要新增一种产品,‌抽象工厂模式的修改会比较复杂,‌因为需要同时修改抽象工厂接口和所有具体工厂类。‌这可能会导致修改的传播,‌影响到现有的代码。‌

5.2.3 不支持单一产品的变化

抽象工厂模式适用于一组相关产品的创建,‌但如果只有一个产品发生变化,‌那么整个工厂都需要进行修改,‌可能不够灵活。‌

5.3 抽象工厂模式优缺点总结

总的来说,‌抽象工厂模式适用于需要创建一组相关产品,‌同时具备高度灵活性和可维护性的场景。‌

6. JDK 中的抽象工厂设计模式示例

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()
  • javax.xml.transform.TransformerFactory#newInstance()
  • javax.xml.xpath.XPathFactory#newInstance()

7. 总结

抽象工厂模式是一种设计模式,‌它属于创建型模式,‌主要用于构建产品族。‌这种模式当有多个抽象角色时使用,‌向客户端提供一个接口,‌使得客户端在不必指定产品的具体情况下,‌能够创建多个产品族中的产品对象。‌抽象工厂模式是所有工厂模式中最抽象和最具一般性的一种形态,‌它针对的是多个产品族结构,‌而不是单个产品系列结构。‌

在抽象工厂模式中,‌每一个工厂负责创建一个产品族,‌而不是单个产品。‌这与工厂方法模式不同,‌后者是针对单个产品系列的。‌抽象工厂模式的实现原理包括将一组相关或相互依赖的对象抽象成产品族,‌每个工厂负责创建一个产品族。‌这种模式允许在不修改客户端代码的情况下增加新的产品族,‌同时保持了代码的灵活性和可扩展性。‌

抽象工厂模式的角色包括:‌

  1. 抽象产品:‌定义了产品的规范和接口。‌
  2. 具体产品:‌实现了抽象产品的接口,‌是实际的产品对象。‌
  3. 抽象工厂:‌提供了创建产品的接口,‌但不负责实现这些接口。‌

抽象工厂模式的优点包括:‌

  1. 灵活性:‌可以轻松扩展新的工厂类,‌支持新的主题或对象类型。‌
  2. 可维护性:‌将对象的创建与使用分离,‌使代码更清晰、‌易于维护。‌
  3. 可靠性:‌避免对象的不正确创建和使用,‌提高代码可靠性。‌

然而,‌抽象工厂模式也存在一些缺点,‌例如不利于添加新种类产品,‌因为每增加一个新产品种类可能需要修改现有的工厂类,‌这违反了开闭原则。‌

相关文章:

Java设计模式-抽象工厂模式-一次性理解透

1. 抽象工厂模式简介 抽象工厂设计模式是创建型模式之一。抽象工厂模式与工厂模式几乎相似,只是它更像工厂中的工厂。 如果您熟悉Java 中的工厂设计模式,或看过上一篇我写的“java简单工厂模式”,您会注意到我们有一个工厂类。此工厂类根据…...

day16-测试自动化之selenium的PO模式

一、PO模式介绍 PO(Page Object)模式是一种在自动化测试中常用的设计模式,将页面的每个元素封装成一个对象,通过操作对象来进行页面的交互。 一般分为六个版本,现在大部分企业都用的V4版本,三层结构…...

Springboot+freemarker大段文本内容动态修改输出,所见即所得

场景:给领导导出数据时,需要给出一个针对专业名词的解释说明,因此会存在有大批量的、大段的文本内容。如果直接写在代码里面,没啥大问题,但是大量的拼接替换、格式样式、后续修改维护等,都不是很方便。如果…...

Kali Linux网络问题解决与静态IP配置技巧

很多用户在使用 Kali Linux 时会遇到无法联网的问题,尤其是在 VMware 虚拟机中。这种情况相当常见,一般都是没有配置DNS服务器或者网卡配置文件的IP和虚拟网络编辑器的IP不一致所导致的,下面我们将探讨如何在 Kali Linux 中配置 DNS 服务和设…...

网络状态码-经验笔记

网络状态码-经验笔记 引言 在网络通信中,HTTP(Hypertext Transfer Protocol)状态码是服务器向客户端(通常是Web浏览器)发送响应时所包含的重要信息之一。 这些状态码指示了客户端请求的结果。 了解并正确使用这些状态…...

c++ 实现 actor 框架

服务端:https://github.com/xukeawsl/coro_actor 客户端:https://github.com/xukeawsl/coro_actor_client...

应对猫咪掉毛挑战,希喂、小米热门宠物空气净化器实测功效PK

随着养宠人群的增多,铲屎官们的需求日益增长,市场上出现了很多品牌的宠物空气净化器。然而,产品质量参差不齐,给消费者选择带来不少困难。劣质宠物空气净化器不仅无法有效去除宠物毛发、皮屑、异味及空气中的有害微粒,…...

0002 保险会计及其特殊性

保险会计是将会计理论专门应用于保险公司的专业会计领域,它是会计学的一个重要分支。作为一个分支,保险会计具有独特的特性,这些特性主要表现在以下几个方面: 产品的无形性:保险产品本质上是一种无形的商品&#xff0c…...

ChatTTS:终极文本转语音工具,支持API!

ChatTTS:终极文本转语音工具,支持API! 文本转语音(TTS)系统的发展已经取得了长足的进步。从最初的机械化、平坦的声音,到如今听起来令人惊讶的人声,ChatTTS作为这一领域的新成员,旨…...

VUE和Element Plus

1.VUE 1.下载和配置环境 使用vue编程,我们需要使用到的编程软件是vs code,还需要使用node.js,这个的作用就类似于JDK,当我们都下载好之后,winR键打开命令提示符,我们在这里可以查看版本, npm…...

Python学习笔记(五)

""" 演示tuple元组的定义和操作 """# 元组一旦定义完成,就不可修改 # 定义元组 # t1 (1, "Hello", True) # t2 () # 定义空元组 # t3 tuple() #定义空元组 # print(f"t1的类型是:{type(t1)}, 内容是&…...

Linux企业级应用(一)构建企业级Linux应用平台:全面指南

文章目录 构建企业级Linux应用平台:全面指南前言1. Linux企业级应用简介2. 构建企业级网站应用平台使用LNMP架构构建Web服务器部署MySQL数据库主从复制与读写分离 3. 实施虚拟化技术部署KVM虚拟化平台使用LVS和Keepalived实现负载均衡与高可用性 4. 文件系统与分布式…...

LeetCode112 路径总和

前言 题目: 112. 路径总和 文档: 代码随想录——路径总和 编程语言: C 解题状态: 成功解答! 思路 比较简单的一个思路是遍历所有的路径,求和后再查找目标值。但是,最好的方法是一边遍历&#x…...

TI AWR1843 毫米波雷达实物展示

引言 随着自动驾驶、工业自动化以及智能交通系统的快速发展,雷达传感器在现代科技中的重要性日益提升。毫米波雷达凭借其高精度测距、抗干扰能力强等特点,逐渐成为各类感知系统中的关键技术。德州仪器(TI)推出的 AWR1843 毫米波雷…...

前端JS总结(下)之事件操作

目录 前言 事件基础 事件的三部分: 常见的事件: 鼠标事件: 键盘事件: 表单事件: onfocus和onblur:获取焦点和失去焦点 onselect:选中单行文本框/多行文本框中的内容 onchange&#xff…...

如何妙用哈希表来优化遍历查找过程?刷题感悟总结,c++实现

先上题目 题目链接:题目链接 这题我最先想到的就是前缀和a,构造好了以后就遍历每一个[l,r]数组(满足题目要求的连续区间数组),奈何倒数第二个样例时间超限 先给出原思路代码 class Solution { public:int subarray…...

【设计模式】漫谈设计模式

这篇文章里说一下对设计模式的个人的理解。本篇文章更类似于随笔而非技术文档。 设计模式最早是在上个世纪就被人提出来了,如今被奉为圣经,也就是GOF等人写的《设计模式》,其中的设计模式,是指导开发者如何进行开发出高内聚、低耦…...

第N5周:Pytorch文本分类入门

本文为365天深度学习训练营 中的学习记录博客原作者:K同学啊 任务: ●1. 了解文本分类的基本流程 ●2. 学习常用数据清洗方法 ●3. 学习如何使用jieba实现英文分词 ●4. 学习如何构建文本向量 一、前期准备 环境安装 这是一个使用PyTorch实现的简单文…...

SpringBoot 自定义 starter

1. 官方文档 SpringBoot 版本 2.6.13,相关链接 Developing with Spring Boot 1.1 什么是 Starter Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and relate…...

TDengine Invalid data format 问题定位

Invalid data format 看语义是数据类型不符,通常这个报错出现在使用行协议写入时。 如果是批量数据写入,想定位是哪条语句的问题,需要查看客户端日志。 如何确定使用的是哪个日志 lsof -p pidof taosadapter | grep taoslog如果没有安装lso…...

Spring Boot 使用 MongoDB 教程

🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法 🔥 微信:zsqtcyw 联系我领取学习资料 …...

Python办公自动化:使用openpyxl 创建与保存 Excel 工作簿

1 创建新的工作簿 在开始任何 Excel 操作之前,首先需要创建一个工作簿。openpyxl 提供了简单的接口来创建新的工作簿。 创建一个空白的工作簿 我们可以使用 openpyxl.Workbook() 来创建一个新的空白工作簿。以下是一个简单的示例: import openpyxl# …...

【张】#11 Union 共用体

Union 共用体可以存储不同的数据类型&#xff0c;但只能同时存储其中的一种类型。 #include <iostream> using namespace std;struct Product {char productName[20];int type;//1 int ,else charunion{int id_int;char id_chars[20];}; };int main(){Product product; …...

Xcode 在原生集成flutter项目

笔者公司有一个从2017年就开始开发的iOS和安卓原生项目&#xff0c;现在计划从外到内开始进行项目迁徙。 1》从gitee拉取flutter端的代码&#xff1b;&#xff08;Android报错Exception: Podfile missing&#xff09; 2》替换Xcode里的cocopods里Podfile的路径 然后报警 然后…...

ES6的promise

Promise是什么 1、Promise是js中的一个原生对象&#xff0c;是一种异步编程的解决方案。可以替换掉传统的回调函数解决方案&#xff0c;将异步操作以同步的流程表达出来。 2、Promise有三种状态&#xff1a;pending(初始化)、fulfilled(成功)、rejected(失败) 可以通过resolve(…...

轻松找回:如何在PostgreSQL 16中重置忘记的数据库密码

目录 1. 引言2. PostgreSQL 16的新特性简介3. 解决方法概述4. 方法一&#xff1a;通过修改pg_hba.conf文件重置密码5. 方法二&#xff1a;通过命令行进入单用户模式6. 方法三&#xff1a;使用pgAdmin工具重置密码7. 总结与最佳实践写在以后 1. 引言 你有没有过这样的经历&…...

EVAL长度突破限制

目录 突破15位限制 代码 绕过方式 第一种&#xff08;使用echo执行&#xff09; 第二种&#xff08;使用file_get_content追加文件后进行问件包含&#xff09; 第三种&#xff08;使用usort可变长参数&#xff09; 突破7位限制 第一种&#xff08;可以使用>创建文件…...

如何判断树上一个点是否在直径上

# 旅游规划 ## 题目描述 W市的交通规划出现了重大问题&#xff0c;市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。但由于人员不足&#xff0c;W市市长决定只在最需要安排人员的路口安排人员。 具体来说&#xff0c;W市的交通网络十分简单&#xff0c;由n个…...

docker 部署 RabbitMQ

命令 docker run -d --namerabbitmq \ -p 5671:5671 -p 5672:5672 -p 4369:4369 \ -p 15671:15671 -p 15672:15672 -p 25672:25672 \ -e RABBITMQ_DEFAULT_USERusername\ -e RABBITMQ_DEFAULT_PASSpassword\ -v /usr/local/rabbitmq/data:/var/lib/rabbitmq \ -v /usr/local/r…...

设计模式 - 过滤器模式

💝💝💝首先,欢迎各位来到我的博客!本文深入理解设计模式原理、应用技巧、强调实战操作,提供代码示例和解决方案,适合有一定编程基础并希望提升设计能力的开发者,帮助读者快速掌握并灵活运用设计模式。 💝💝💝如有需要请大家订阅我的专栏【设计模式】哟!我会定…...

孝感市门户网站/个人如何在百度做广告

如何選擇1個適合您的 charging ic 呢&#xff1f;主要考量以下 parameters charging ic 的 IIN, VINcharging ic 給 battery 的 IIN, VINsystem VINspecial features&#xff1a;power path&#xff0c;otg&#xff0c;jeitabattery chemistry, series or parallel  you can …...

黄石网站建设哪家好/seo搜索优化待遇

控制报文协议&#xff08;Internet Control Message Protocol&#xff0c;ICMP&#xff09;是 TCP/IP 协议族的一个子协议。ICMP 协议用于在 IP 主机和路由器之间传递控制消息&#xff0c;描述网络是否通畅、主机是否可达、路由器是否可用等网络状态。 由于 IP 协议简单&#x…...

四川省城乡住房与建设厅网站首页/营销推广公司案例

目录 一:MSMQ的一些理论上的知识二:队列类型&#xff08;Queue Type&#xff09;三:安装消息队列四:在C#中Messagequeue class五:MSMQ-发送消息到远程专用队列六:例子一、在学习Messagequeue 类之前,首先介绍一下MSMQ的一些理论上的知识 MSMQ(MicroSoft Message Queue…...

网站建设推广公司排名/百度快照查询

nslookup # ipv4 nslookup 域名 # ipv6 nslookup -queryAAAA 域名...

燕郊做网站找谁/指数查询

视频效果 炫酷按钮思路&#xff1a; 大致实录就是将盒子里边的before倾斜变形&#xff0c;使其变成一个平行四边形的效果&#xff0c;然后将其缩小隐藏&#xff0c;在放大&#xff0c;添加过渡时间就会出现如图所示的效果 代码&#xff1a; <!DOCTYPE html> <html l…...

wordpress安装主题提示服务器错误/在线刷高质量外链

创建数据表 普通创建表&#xff1a;create table 表名(字段名 字段类型[字段属性],字段名 字段类型[字段属性],…)[表选项] create table mydatabase.class( -- mydatabase是已经存在的数据库name varchar(10))charset utf8;查询表 show tables; – 查看所有表 show tables l…...