Java设计模式详解:抽象工厂模式

Java设计模式详解:抽象工厂模式


文章目录

  • Java设计模式详解:抽象工厂模式
  • 前言
  • 一、原理
  • 二、案例实战:打造一款汽车生产流水线
  • 三、使用场景
  • 四、与工厂模式的区别
  • 总结


前言

对于初学者来说,设计模式可能显得有些抽象和复杂,但其实它就像一辆汽车,每个模式都是汽车上的一个零件,各有用途,但组合起来就能解决各种复杂问题。抽象工厂模式也不例外,它是创建型设计模式中的一种,用于创建一系列相互关联或相互依赖的对象,而无需指定它们具体的类。


一、原理

抽象工厂模式的核心思想就是提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。它包含一个工厂接口和多个工厂实现,每个工厂实现都负责创建一系列对象。这样,当我们需要改变所创建的对象类型时,只需要更换对应的工厂实现即可,而不需要修改客户端代码。

抽象工厂模式的原理,咱们可以通过一个生产车子的例子来类比一下:

想象一下,你是汽车生产线的负责人,你想要生产不同品牌的车子,比如小米汽车、宝马和奔驰。每种品牌的车子都包含车身、发动机和轮胎等部件。为了高效且灵活地生产这些车子,你采用了抽象工厂模式。

首先,你定义了一个“车子生产工厂”的接口,这个接口里面包含了生产车身、发动机和轮胎的方法。然后,你为每个品牌创建了一个具体的工厂实现,比如小米汽车工厂、宝马工厂和奔驰工厂。小米汽车工厂负责按照小米的秘方来生产并组装小米汽车的车身、发动机和轮胎,宝马工厂负责按照宝马的秘方来生产宝马车身、宝马发动机和宝马轮胎。同样,奔驰工厂则负责生产奔驰系列的车身、发动机和轮胎。

作为生产线负责人的你,只需要告诉工人(客户端代码):“我要生产小米车子。”工人就会去调用“车子生产工厂”的接口,并把这个需求交给小米汽车工厂。小米汽车工厂就会按照小米的秘方,给你生产出一辆完整的小米车子。

如果你想换生产奔驰车子,也只需要告诉工人:“这次我要生产奔驰车子。”工人同样通过接口去调用奔驰工厂,奔驰工厂就会按照奔驰的秘方生产车子。

在整个生产过程中,你作为负责人,不需要关心车子是怎么生产出来的,只需要告诉工人要生产哪个品牌的车子。而且,如果你想换品牌,只需要告诉工人换个工厂,不需要去改动整个生产线的结构。

这就是抽象工厂模式的原理:通过一个统一的接口来创建一系列相关的对象,而且你可以很方便地更换不同的工厂实现,来生产不同类型的对象。这样一来,生产线就更加灵活,也更容易扩展和维护了。

二、案例实战:打造一款汽车生产流水线

假设我们要打造一款汽车生产流水线,可以生产不同品牌的汽车,每个品牌的汽车都有发动机和轮胎等部件。我们可以定义一个抽象的工厂接口,包含创建发动机和轮胎的方法,然后为每个品牌创建一个具体的工厂实现。

// 抽象产品接口  
public interface Engine {  void start();  
}  public interface Tire {  void change();  
}  // 宝马发动机  
public class BMWEngine implements Engine {  @Override  public void start() {  System.out.println("宝马发动机启动");  }  
}  // 宝马轮胎  
public class BMWTire implements Tire {  @Override  public void change() {  System.out.println("更换宝马轮胎");  }  
}  // 小米发动机  
public class XiaoMiEngine implements Engine {  @Override  public void start() {  System.out.println("小米发动机启动");  }  
}  // 小米轮胎  
public class XiaoMiTire implements Tire {  @Override  public void change() {  System.out.println("更换小米轮胎");  }  
}  // 抽象工厂接口  
public interface CarFactory {  Engine createEngine();  Tire createTire();  
}  // 宝马汽车工厂实现  
public class BMWFactory implements CarFactory {  @Override  public Engine createEngine() {  return new BMWEngine();  }  @Override  public Tire createTire() {  return new BMWTire();  }  
}  // 小米汽车工厂实现  
public class XiaoMiFactory implements CarFactory {  @Override  public Engine createEngine() {  return new XiaoMiEngine();  }  @Override  public Tire createTire() {  return new XiaoMiTire();  }  
}  // 客户端代码  
public class FactoryClient {  public static void main(String[] args) {  // 使用小米工厂创建小米品牌的发动机和轮胎  CarFactory xiaoMiFactory = new XiaoMiFactory();  Engine xiaoMiEngine = xiaoMiFactory.createEngine();  Tire xiaoMiTire = xiaoMiFactory.createTire();  xiaoMiEngine.start();  xiaoMiTire.change();  System.out.println("生产了小米的发动机和轮胎");  // 如果需要换其他品牌,只需要更换工厂实现即可  // 例如使用宝马工厂创建宝马品牌的发动机和轮胎  // CarFactory bmwFactory = new BMWFactory();  // Engine bmwEngine = bmwFactory.createEngine();  // Tire bmwTire = bmwFactory.createTire();  // bmwEngine.start();  // bmwTire.change();  // System.out.println("生产了宝马的发动机和轮胎");  }  
}

三、使用场景

以下是一些适用抽象工厂模式的情况:

  1. 当需要独立于具体产品创建时
    当系统的核心逻辑不应依赖于具体产品的实现细节时,可以使用抽象工厂模式。这样,系统可以灵活地更换产品系列,而无需修改核心代码。
  2. 当需要配置多个产品系列时
    当系统需要根据不同的配置或需求,从多个产品系列中选择合适的产品进行组合时,抽象工厂模式非常适用。它提供了统一的接口,使得系统可以方便地切换不同的产品系列。
  3. 当强调产品间的关联性时
    当一系列产品需要联合使用,且它们之间存在依赖或关联性时,抽象工厂模式能够确保这些产品始终一起使用,避免不兼容或错误配置的问题。
  4. 当提供产品接口而隐藏实现时
    如果你希望为外部用户提供产品接口,但不想暴露具体的实现细节,抽象工厂模式是一个很好的选择。通过定义抽象工厂和抽象产品接口,你可以只展示接口,而将实现细节隐藏起来。

例如,当系统需要支持多平台或多环境时,你可以为不同的操作系统或设备类型定义不同的产品系列,并使用抽象工厂模式来创建和配置这些产品。

四、与工厂模式的区别

抽象工厂模式和工厂模式在Java设计模式中都属于创建型模式,它们的核心目标都是为了将对象的创建与使用解耦,从而提高系统的灵活性和可维护性。然而,在具体实现和应用场景上,两者存在明显的差异:

  1. 产品种类的覆盖范围
    ①工厂方法模式主要针对单一产品等级结构,它负责创建某一种类的产品对象。当系统中只需要一个系列的产品时,工厂方法模式能够很好地满足需求。
    ②抽象工厂模式则面向多个产品等级结构,能够创建一系列相关的或相互依赖的产品对象。当系统需要同时处理多个系列的产品时,抽象工厂模式更为适用。

  2. 系统的扩展性
    ①工厂方法模式在增加新产品对象时,只需要添加新的具体产品类和对应的工厂类,而无需修改现有的代码结构,因此在扩展新产品方面具有优势。
    ②抽象工厂模式在增加新的产品系列时,虽然也需要添加新的具体产品类,但可能还需要修改抽象工厂接口以及所有实现了该接口的具体工厂类。因此,在扩展新产品系列方面,它的灵活性稍逊于工厂方法模式。

  3. 管理的复杂性
    ①抽象工厂模式通过在一个工厂中集中管理多个产品系列的创建,降低了系统管理的复杂性。它能够在类的内部对产品族中相关联的多等级产品共同管理,避免了引入多个新类来分别管理不同产品系列的复杂性。
    ②工厂方法模式虽然在单一产品系列的管理上较为简单,但当面对多个产品系列时,可能需要引入更多的工厂类来进行管理,从而增加了系统的复杂性。

综上所述,工厂方法模式和抽象工厂模式在适用场景、扩展性和管理复杂性方面存在差异,不过个人觉得差异并不是很大,相对来说,抽象工厂模式是工厂模式的一个功能性上的补充。在选择使用哪种模式时,还是应该根据具体的需求和场景进行权衡,选择一个更合适当前业务的方案。普遍适用:当只需要处理单一产品系列时,工厂方法模式更为合适;而当需要处理多个相关产品系列时,抽象工厂模式则更具优势


总结

抽象工厂模式是一种非常强大的设计模式,它能够帮助我们解耦对象的创建逻辑,使得系统更加灵活和可扩展。但是,也要注意不要过度使用,因为过多的抽象和工厂类可能会增加系统的复杂性和维护成本。所以,在决定是否使用抽象工厂模式时,一定要根据具体需求和场景来权衡利弊。

好了,今天关于抽象工厂模式的分享就到这里,希望对你们能有所帮助。如果你还有其他问题或者想要了解更多设计模式的内容,欢迎在评论区留言!

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

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

相关文章

1.4 掌握Scala运算符

大家好,今天我们将一起探讨Scala中的运算符。在Scala中,运算符实际上就是方法的一种特殊形式。这意味着我们可以像调用方法一样使用运算符。 首先,让我们了解一下Scala中的运算符种类。Scala支持多种类型的运算符,包括算术运算符…

IT廉连看——SpringBoot——SpringBoot快速入门

IT廉连看——SpringBoot——SpringBoot快速入门 1、idea创建工程 &#xff08;1&#xff09;普通Maven工程创建 工程名spring-boot-test 2、添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/PO…

windows7安装高版本Node

项目需要安装高版本得node&#xff0c;windows7最高支持到v13&#xff0c;需要手动下载zip安装包进行解压&#xff0c;配置环境变量&#xff0c;添加路径到path&#xff0c;如果安装了nvm需要卸载&#xff0c;否则配置得高版本node可能不生效&#xff0c;成功后如下&#xff1a…

LeetCode 24.两两交换链表中的节点

给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1,4…

Mysql语句(更新)

查询框架 执行顺序select 查询列表 7from 表 1[join type] join 表2 2 on 连接条件 3where 筛选条件 4group by 分组条件 5having 分组后筛选 6or…

机器学习(Machine Learning)知识点

机器学习Machine Learning知识点 机器学习1. 常用的数据处理的库有哪些2. 常用的机器学习的库有哪些3. 过拟合问题的特点4. 过拟合问题的解决方法&#xff1a;5. 说一下广度优先遍历和深度优先遍历&#xff1f;6. 什么是线性回归?7. 机器学习中&#xff0c;有哪些损失函数&…

Java常用API_正则表达式_字符串的替换和截取方法——小练习

我将通过一个练习题来展示这两个方法 练习题&#xff1a; 有一段字符串&#xff1a;小张qwertyuiop123小李asdfghjkl456小王 要求1&#xff1a;把字符串中三个姓名之间的字母替换成vs 要求2&#xff1a;把字符串中的三个姓名切割出来 编写代码&#xff1a; public class Tes…

js,uniapp,vue,小写数字转化为大写

应用场景&#xff1a; 把1、2、3&#xff0c;转为一、二、三 方法&#xff1a; retBigSrt(num) {const changeNum [零, 一, 二, 三, 四, 五, 六, 七, 八, 九]const unit [, 十, 百]num parseInt(num)const getWan (temp) > {const strArr temp.toString().split().re…

day12 函数基础(三)

一.迭代器(了解) 迭代:更新换代 迭代特点:每一次迭代得到的值,就是下一个迭代的初始值 可迭代对象: 字符串 列表 元组 字典 集合 ...... 迭代器的语法格式: ```python 变量名 = iter(可迭代对象) 变量名 = 可迭代对象._iter_ # 迭代取值格式 迭代器名._next_() next(迭代器…

马斯克推出Grok-1.5,接近GPT-4级别的性能

定于下周发布的Grok-1.5带来了增强的推理和解决问题的能力&#xff0c;并接近于已知的开源和闭源的LLM的性能&#xff0c;包括OpenAI的GPT-4和Anthropic的Claude 3。 马斯克指出&#xff0c;Grok-1.5将为xAI在X平台上的ChatGPT挑战者聊天机器人提供支持&#xff0c;而Grok-2(新…

2024.3.26力扣每日一题——设计可以求最短路径的图类

2024.3.26 题目来源我的题解方法一 Dijkstra算法求最短路径方法二 Floyd算法求最短路径 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2642 我的题解 方法一 Dijkstra算法求最短路径 图使用邻接表存储&#xff0c;添加边只需要更新邻接表就行。 求两个节点的路径最小代…

交易要想成功澳福总结几点

100%使用基本面分析的投资者能保证每次交易都能成功吗&#xff1f;100%使用技术分析的投资者能保证每次交易都能成功吗&#xff1f;在fpmarkets澳福看来无论是基本面分析还是技术分析都不能保证100%交易成功。 投资者不能只依赖一种分析进行投资交易。在fpmarkets澳福看来成功的…

GD32F470_US-016 模拟电压输出 双量程 模拟量 超声波测距模块 高精度

2.18 US-016电压式超声波测距传感器 US-016是市场上唯有的一款模拟量输出的超声波测距模块&#xff0c;输出的模拟电压和距离值成正比&#xff0c;可以方便的和其他系统相连&#xff0c;US-016工作稳定可靠。 US-016超声波测距模块可实现2cm~3m的非接触测距功能&#xff0c;供…

掌握Go语言:Go语言错误处理,从基础到高级,让你的代码更健壮!(33)

Go 语言的错误处理机制非常灵活&#xff0c;它通过错误值&#xff08;error&#xff09;来表示可能发生的错误&#xff0c;并提供了多种处理错误的方法和技巧。除了基本的错误处理方式外&#xff0c;还有一些高级用法可以进一步提升代码的健壮性和可读性。 Go 语言的错误处理基…

【LeetCode热题100】74. 搜索二维矩阵(二分)

一.题目要求 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;…

Dapr(四) Dapr核心组件的使用二

结合前三期 Dapr(一) 基于云原生了解Dapr(Dapr(一) 基于云原生了解Dapr-CSDN博客) Dapr(二) 分布式应用运行时搭建及服务调用(Dapr(二) 分布式应用运行时搭建及服务调用-CSDN博客) Dapr(三) Dapr核心组件的使用一(Dapr(三) Dapr核心组件的使用一-CSDN博客)。下一期使用Dapr中的…

【LeetCode热题100】34. 在排序数组中查找元素的第一个和最后一个位置(二分)

一.题目要求 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 二.题…

LangChain-12 Routing By Semantic Similarity 让GPT根据不明确的问题 自动选择工具集 根据语义自动路由

问题背景 平常我们设计程序的时候&#xff0c;会这么写&#xff1a; // 随便举例 String type paramDTO.getType(); if (type.equals("吃饭")) {// do } else if (type.equals("喝水")) {// do } else {// do }此时如果type传入的不是数字&#xff0c;那…

docker使用arthas基本教程

供参考也是自己的笔记 docker容器下使用遇到的问题&#xff1a;大致是连接不上1号进程 我这边主要的问题是用户权限问题&#xff0c;docker容器使用aaa用户启动&#xff0c;那个在docker容器内&#xff0c;需要使用aaa用于启动 docker 容器如何使用arthas #实现下载好arthas …

前端开发语言都有哪些?

前端开发主要涉及以下几种语言&#xff1a; HTML (HyperText Markup Language)&#xff1a;作为网页内容的骨架&#xff0c;定义了网页的结构和内容。是所有Web开发者必须掌握的基础语言。CSS (Cascading Style Sheets)&#xff1a;用于设置网页的样式和布局&#xff0c;包括字…