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

news2024/9/22 1:51:36

抽象工厂模式示意图

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();
     
    @Override
    public 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;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public 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;
    }
    @Override
    public String getRAM() {
        return this.ram;
    }
 
    @Override
    public String getHDD() {
        return this.hdd;
    }
 
    @Override
    public 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;
	}
	@Override
	public 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;
	}
	
	@Override
	public 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. 可靠性:‌避免对象的不正确创建和使用,‌提高代码可靠性。‌

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2037241.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WPF篇(18)-DataGrid数据表格控件+ComboBox下拉框控件

DataGrid数据表格控件 DataGrid是一个可以多选的数据表格控件。所以,它继承一个支持多选的父类——MultiSelector。 public abstract class MultiSelector : Selector {protected MultiSelector();public IList SelectedItems { get; }protected bool CanSelectMu…

Animetronic - hackmyvm

简介 靶机名称:Animetronic 难度:简单 靶场地址:https://hackmyvm.eu/machines/machine.php?vmAnimetronic 本地环境 虚拟机:vitual box 靶场IP(Animetronic):192.168.130.188 windows_…

Golang 为何如此之快:性能分析

Golang 是一种相对年轻但很流行的语言,IBM 和 Google 等公司都在使用这种语言。在本文中,我们将了解 Golang 的特别之处。 Golang 被认为是世界上编译速度最快的语言之一。谷歌、Uber 和 Twitch 等科技公司都喜欢使用它,并依靠它进行内部开发…

HarmonyOS(50) 截图保存功能实现

componentSnapshot实现截图 前言权限配置和申请权限配置权限申请 componentSnapshot截图实现将PixelMap转换成图片格式保存截图到系统相册保存截图到应用沙箱全部源码参考资料 前言 HarmonyOS提供了componentSnapshot实现组件截图功能,可以将UI截图成为image.Pixel…

WMS助力企业数字化转型(七)

WMS系统可以帮助企业实现更精确的库存控制,避免库存积压和缺货现象。通过对历史数据的分析,企业可以预测需求趋势,优化库存结构,从而减少资金占用和运营成本。同时,WMS还支持与其他系统的无缝对接,如企业资…

限时营销与开源AI智能名片O2O商城小程序的深度融合:重塑线上促销策略的新视角

摘要:在数字化营销日益激烈的今天,限时促销活动作为吸引用户注意力、激发购买欲望的传统手段,面临着前所未有的挑战。随着线上营销活动的泛滥,消费者对传统折扣策略已逐渐产生疲劳与免疫。因此,探索一种更加高效、精准…

开放式耳机最不伤耳吗?舒适度高的几款精选蓝牙耳机

开放式耳机对耳朵的伤害相对较小,但不能说它是最不伤耳的耳机。 与传统入耳式耳机相比,开放式耳机的优点在于不会深入耳道,减少了对耳朵的压迫感和耳道内的压力,佩戴起来更加舒适。同时,开放式设计允许空气流通&#…

免费简单的制作3D卡通建模——Fuse软件和Readyplayer的使用介绍

最终效果 文章目录 最终效果一、使用Fuse软件去Steam下载安装捏人选择身体部位自定义人物细节参数换装贴图修改导出OBJ文件即可 二、使用ReadyplayerReadyplayer官网地址选择从模板开始,或者拍照选择图片进行捏脸将模型导入Unity通过Readyplayer官方插件导入模型通过…

白盒测试-发送请求-引出MockMvc源码类

白盒测试是什么? 一般是测开做白盒测试,研发做白盒 spring boot是和junit结合 原本是jmeter发请求,是看不到代码逻辑,有接口信息就可以实现 用测试代码发请求,能看到代码逻辑,比接口测试更全面&#xf…

大恒相机通过Line2或Line3直接给出3.3V触发,形成分时曝光

大恒相机通过Line2或Line3直接给出3.3V触发,形成分时曝光 一、分时曝光需求二、3.3V信号分时曝光设计 写在前面 上班了,没多少时间再去精度论文了,大多是项目上的事情。 一、分时曝光需求 一般的12V光源通过光源控制器与大恒相机Line1线连接…

PDF转换器推荐:轻松将图片批量转为PDF

高质量的图片与文档管理已经逐渐成为了我们日常工作中不可或缺的一部分。为了防止图片在传输的过程中被压缩,我经常将他们转换为PDF格式。这次我给你推荐几个我常用的图片转PDF的小工具吧。 1.福昕PDF转换大师 链接一下>>https://www.pdf365.cn/pdf2word/ …

关于自己部署AI大模型踩的坑(一)——硬件篇

最近一直在研究如何打算属于我自己的J.A.R.V.I.S.(钢铁侠中的机器人管家)。 上一篇写了我最近在部署自己的大模型,使用llama3.1, 和通义千问2。虽然最终结果也是成功了,过程却十分地坎坷。 所以这一篇文章一是总结其中…

keepalived基础

目录 1 高可用集群简介 1.1 高可用的概念 1.2 常见的 HA 集群 1.3 高可用集群软件 2 keepalived的功能与用途 2.1 LVS directors failover功能 2.2 LVS cluster nodes healthchecks功能 3 VRRP协议介绍 4 Keepalived 架构 5 原理总结 1 高可用集群简介 1.1 高可用的概念 高可…

数据埋点系列 5|数据驱动决策:形成数据驱动文化

在过去的几篇文章中,我们深入探讨了数据埋点、数据质量保证、数据分析和可视化等主题。现在,让我们站在更高的视角,讨论如何将这些技术和方法整合到实际的业务决策中,以及如何在组织中建立真正的数据驱动文化。 目录 1. 回顾&am…

Github 2024-08-14 C开源项目日报Top10

根据Github Trendings的统计,今日(2024-08-14统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目10Objective-C项目1PHP项目1Python项目1PHP:流行的Web开发脚本语言 创建周期:4710 天开发语言:C, PHP协议类型:OtherStar数量:37340 …

【Pyspark-驯化】一文搞懂Pyspark修改hive表描述以及增加列使用技巧

【Pyspark-驯化】一文搞懂Pyspark修改hive表描述以及增加列使用技巧 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 相关内容文档获取 微…

C++11 STL中的Vector使用细节

容器 支持泛型 Vector常用成员函数示例迭代器操作插入和删除操作 与find 配合:vector 一些复杂操作 Vector 的内存管理策略压入对象 需要无参构造.压入对象指针 高效插入和删除 迭代器失效 代码优化: 二维及多维空间生成 容器 支持泛型 vector<int> vi;vector<double…

中国数据库的前世今生:披荆斩棘,乘风破浪

文章目录 前言国外数据库技术蓬勃发展中国信息化起步与发展&#xff08;数据库技术探索&#xff09;国外数据库商战策略解决燃眉之急学习先进技术 数据库技术的新格局雷声大雨点小的千年虫新型数据库的诞生国产数据库展露头脚 开源助力国产数据库弯道超车去“IOE”化大数据席卷…

使用OIDC登录kubesphere遇到的坑细节

1.通过代理telepresence到本地调试&#xff0c;使用默认账号密码&#xff0c;提示账号密码错误。 2.kubesphere在sso登录的时候&#xff0c;提示签名错误&#xff0c;其实这个错误不是很明确&#xff0c;所以要到本地调试&#xff0c;找到根本原因。 # 错误1 Tnauthorized: fa…

《Linux运维总结:基于ARM64架构CPU使用docker-compose一键离线部署etcd 3.5.15容器版分布式集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面对不同的客户部署业务系统&#xff0…