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

【设计模式】抽象工厂模式

抽象工厂模式(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 传递形状信息 ShapeCIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 ColorRED / GREEN / BLUE),以便获取它所需对象的类型。

抽象工厂模式的 UML 图

步骤 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 就特别喜欢这个字符串。所以,她想改变至多一个字符(或者不做任何改变&#xf…...

编写第一个 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 移除元素: 题目内容如下: 假设一个数组为&#xff1…...

【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管理项目&#xff0c…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​,覆盖应用全生命周期测试需求,主要提供五大核心能力: ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来&#xf…...

如何为服务器生成TLS证书

TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...