【设计模式】抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
介绍
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
抽象工厂模式包含以下几个核心角色:
- 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。
- 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。
- 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。
- 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
抽象工厂模式通常涉及一族相关的产品,每个具体工厂类负责创建该族中的具体产品。客户端通过使用抽象工厂接口来创建产品对象,而不需要直接使用具体产品的实现类。
实现
我们将创建 Shape 和 Color 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactory 和 ColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer。
AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 Shape(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 Color(RED / GREEN / BLUE),以便获取它所需对象的类型。
步骤 1
为形状创建一个接口。
Shape.java
public interface Shape {void draw();
}
步骤 2
创建实现接口的实体类。
Rectangle.java
Rectangle.java
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}
Square.java
public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}
Circle.java
public interface Color {void fill();
}
步骤 3
为颜色创建一个接口。
Color.java
public interface Color {void fill();
}
步骤4
创建实现接口的实体类。
Red.java
public class Red implements Color {@Overridepublic void fill() {System.out.println("Inside Red::fill() method.");}
}
Green.java
public class Green implements Color {@Overridepublic void fill() {System.out.println("Inside Green::fill() method.");}
}
Blue.java
public class Blue implements Color {@Overridepublic void fill() {System.out.println("Inside Blue::fill() method.");}
}
步骤 5
为 Color 和 Shape 对象创建抽象类来获取工厂。
AbstractFactory.java
public abstract class AbstractFactory {public abstract Color getColor(String color);public abstract Shape getShape(String shape);
}
步骤 6
创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){if(shapeType == null){return null;} if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}@Overridepublic Color getColor(String color) {return null;}
}
ColorFactory.java
public class ColorFactory extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){return null;}@Overridepublic Color getColor(String color) {if(color == null){return null;} if(color.equalsIgnoreCase("RED")){return new Red();} else if(color.equalsIgnoreCase("GREEN")){return new Green();} else if(color.equalsIgnoreCase("BLUE")){return new Blue();}return null;}
}
步骤 7
创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。
FactoryProducer.java
public class FactoryProducer {public static AbstractFactory getFactory(String choice){if(choice.equalsIgnoreCase("SHAPE")){return new ShapeFactory();} else if(choice.equalsIgnoreCase("COLOR")){return new ColorFactory();}return null;}
}
步骤 8
使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {public static void main(String[] args) {//获取形状工厂AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");//获取形状为 Circle 的对象Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取形状为 Rectangle 的对象Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取形状为 Square 的对象Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();//获取颜色工厂AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");//获取颜色为 Red 的对象Color color1 = colorFactory.getColor("RED");//调用 Red 的 fill 方法color1.fill();//获取颜色为 Green 的对象Color color2 = colorFactory.getColor("GREEN");//调用 Green 的 fill 方法color2.fill();//获取颜色为 Blue 的对象Color color3 = colorFactory.getColor("BLUE");//调用 Blue 的 fill 方法color3.fill();}
}
步骤 9
执行程序,输出结果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
相关文章:

【设计模式】抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在抽象工厂模式中,接口是负责创建一个相关对象…...

小白带你学习linux的Redis3.2集群(三十三)
目录 一、Redis主从复制 1、概念 2、作用 3、缺点 4、流程 5、搭建 6、验证 二、Reids哨兵模式 1、概念 2、作用 3、缺点 4、结构 5、搭建 6、验证 三、Redis集群 1、概述 2、原理 3、架构细节 4、选举过程 四、搭建 1、第一步现在外部使用finalshell 9.9…...

嵌入式技术,就在你的手边!
嵌入式技术,听起来多么高大上的名词,同时它也确实是当今信息技术的前沿领域,但这并不意味着它就距离我们很遥远。 事实恰恰相反,在当今科技发展迅猛的时代,嵌入式技术成为了人们生活中不可或缺的一部分。它以其小巧、高…...

nodejs+vue+elementui健康饮食美食菜谱分享网站系统
本系统采用了nodejs语言的vue框架,数据采用MySQL数据库进行存储。结合B/S结构进行开发设计,功能强大,界面化操作便于上手。本系统具有良好的易用性和安全性,系统功能齐全,可以满足饮食分享管理的相关工作。 语言 node.…...

input 设置type=“number“,鼠标悬停关闭提示语
一、问题 最近刚发现input 设置type"number"之后,鼠标悬停会出现提示语:请输入有效值。两个最接近的有效值分别为xx和xx。想要输入的值确实为number格式,又可以输入小数,不限制小数位,所以要把这讨厌的提示去…...

CSDN互利共赢玩法实战!!!
csdn项目第一波基本都顺利跑了起来,我们总计找来了一两千个新的项目源码,来让大家变现。 在实战中,主要两个玩法,一个引流,一个付费资源。付费资源门槛越来越高,所以我们这一波升级完成的号,就非…...

java.sql.SQLFeatureNotSupportedException 问题及可能的解决方法
目录 问题 分析: 解决方法 问题 java.sql.SQLFeatureNotSupportedException 分析: 可能是你的 druid的maven依赖版本太低了,我的以前是1.1.16,就出现了异常! 解决方法 把druid的maven依赖版本调高! 运…...

如何在 .NET Core WebApi 中处理 MultipartFormDataContent 中的文件
问题描述# 上图示例展示了用户通过 IOS 客户端发送请求时,对应后端接口接收到的 Request 内容。从请求内容的整体结果,我们可以看出这是一个 multipart/form-data 的数据格式,由于这种数据是由多个 multipart section 组成,所以我…...

【智力悬疑题】——【“找凶手”解法】
“找凶手”题目解法 “案件题目”💻 某地发生了一起凶杀案,警察通过排查确定杀人凶手必为4个嫌疑犯中的一个。以下为4个嫌疑犯的供词: A说:不是我。 B说:是C。 C说:是D。 D说:C在胡说。 已知3个…...

【论文阅读】基于深度学习的时序异常检测——TimesNet
系列文章链接 参考数据集讲解:数据基础:多维时序数据集简介 论文一:2022 Anomaly Transformer:异常分数预测 论文二:2022 TransAD:异常分数预测 论文三:2023 TimesNet:基于卷积的多任…...
P3741 honoka的键盘
题目背景 honoka 有一个只有两个键的键盘。 题目描述 一天,她打出了一个只有这两个字符的字符串。当这个字符串里含有 VK 这个字符串的时候,honoka 就特别喜欢这个字符串。所以,她想改变至多一个字符(或者不做任何改变…...

编写第一个 React Native 程序
React Native 目录 使用React Native CLI命令创建的目录如下图所示: 重要目录说明 目录说明__tests__存放测试用例的目录.bundle / config配置文件(一般不会用到)android 和 IOS 文件夹这两个文件夹主要是存放安卓和 ios 相关的配置文件和…...

AI:03-基于深度神经网络的低空无人机目标检测图像识别的研究
文章目录 数据集收集与预处理深度神经网络模型设计模型训练与优化目标检测与图像识别代码实现:实验结果与分析讨论与展望低空无人机的广泛应用为许多领域带来了巨大的潜力和机会。为了实现无人机的自主导航和任务执行,准确的目标检测和图像识别是至关重要的。本文旨在研究并提…...

Arcgis将一个shp依照属性表导出为多个shp
# -*- coding:utf-8 -*-import arcpy import osfrom arcpy import env#env.workspace "./" #自己设置路径shp rC:\Users\Administrator\Desktop\Lake\xxx.shp #shp文件路径outpath r"C:\Users\Administrator\Desktop\Lake\fenli" #输出结果路径with arc…...
LeetCode.26,27,88三题-双指针的运用
本文将对3道解决方法类似的题目进行逐一分析,这三道题目分别是: LeetCode.26 删除有序数组中的重复项 LeetCode.27 移除元素 LeetCode.88 合并两个有序数组 1. LeetCode.27 移除元素: 题目内容如下: 假设一个数组为࿱…...

【Django】招聘面试管理01 创建项目运行项目
文章目录 前言一、创建项目二、运行项目三、访问后台管理页面四、配置项总结 前言 跟着视频学一学,记录一下。 一、创建项目 照着步骤创建虚拟环境,安装Django等依赖包,创建项目:【Django学习】01 项目创建、结构及命令 > d…...
C# 数据类型
C# 数据类型 一、整数类型(Integral Types)1.sbyte2.byte3.short4.ushort5.int6.uint7.long8.ulong 二、浮点数类型(Floating-Point Types)1.float2.double3.decimal 三、字符类型(Character Type)1.char 四…...

竞赛项目 深度学习手势识别算法实现 - opencv python
文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习手势识别算法实现 - opencv python 该项目较为新颖…...

前端进阶html+css04----盒子模型
1.一个盒子由content(文本内容),padding,border,margin组成。 2.盒子的大小指的是盒子的宽度和高度。一般由box-sizing属性来控制。 1)默认情况下, 也就是box-sizing: content-box时,盒子的宽高计算公式如下: 盒子宽…...

Go Web--Go Module
目录 一、Go Module 1、开启Go Module 2、Go Module基本操作 3、使用GoLand创建Go Module项目 4、GoLand配置File Watchers 一、Go Module Go Module包管理工具----相当于Maven 1.11版本引入 1.12版本正式支持 告别GOPATH,使用Go Module管理项目,…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...