工厂模式 与 抽象工厂模式 的区别
工厂模式:
// 抽象产品接口
interface Product {void showInfo();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void showInfo() {System.out.println("This is Product A");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic void showInfo() {System.out.println("This is Product B");}
}// 抽象工厂类
abstract class Creator {abstract Product createProduct();
}// 具体工厂A,生产产品A
class ConcreteCreatorA extends Creator {@OverrideProduct createProduct() {return new ConcreteProductA();}
}// 具体工厂B,生产产品B
class ConcreteCreatorB extends Creator {@OverrideProduct createProduct() {return new ConcreteProductB();}
}public class FactoryMethodExample {public static void main(String[] args) {Creator creatorA = new ConcreteCreatorA();Product productA = creatorA.createProduct();productA.showInfo();Creator creatorB = new ConcreteCreatorB();Product productB = creatorB.createProduct();productB.showInfo();}
}
在这个示例中,Product 是抽象产品接口,ConcreteProductA 和 ConcreteProductB 是具体的产品类。Creator 是抽象工厂类,ConcreteCreatorA 和 ConcreteCreatorB 是具体的工厂类,分别生产不同的产品。在场景类中,通过具体的工厂来创建不同的产品,而无需直接涉及具体产品的实现类。这就是工厂方法模式的正确用法。
抽象工厂模式:
// 抽象产品接口
interface ProductA {void showInfo();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {@Overridepublic void showInfo() {System.out.println("This is Product A1");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {@Overridepublic void showInfo() {System.out.println("This is Product A2");}
}// 抽象产品接口
interface ProductB {void showInfo();
}// 具体产品B1
class ConcreteProductB1 implements ProductB {@Overridepublic void showInfo() {System.out.println("This is Product B1");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {@Overridepublic void showInfo() {System.out.println("This is Product B2");}
}// 抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}public class AbstractFactoryExample {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();productA1.showInfo();productB1.showInfo();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.showInfo();productB2.showInfo();}
}
在这个示例中,AbstractFactory 是抽象工厂接口,ConcreteFactory1 和 ConcreteFactory2 是具体工厂类,分别生产不同系列的产品。每个具体工厂类实现了创建一组相关产品的方法。这就是抽象工厂模式的示例。
区别:
抽象工厂模式(Abstract Factory Pattern)和工厂方法模式(Factory Method Pattern)是两种不同的设计模式,它们都属于创建型模式,用于创建对象。它们之间的区别在于抽象程度和用途。
-
抽象工厂模式:
- 抽象工厂模式用于创建一组相关或相互依赖的对象,这些对象通常属于不同的产品族。
- 它包含一个抽象工厂接口,该接口声明了一组用于创建不同类型产品的抽象方法。每个具体工厂类实现了这些方法以创建特定产品族的对象。
- 抽象工厂模式强调创建一组对象,通常涉及多个产品接口和多个产品实现类。
-
工厂方法模式:
- 工厂方法模式用于创建单一对象,但是通过子类来决定实例化哪个类。
- 它包含一个抽象工厂基类(接口或抽象类),该基类声明了一个用于创建对象的抽象方法。每个具体工厂子类实现这个方法以返回特定的产品对象。
- 工厂方法模式强调创建单一对象,每个工厂子类负责创建一种产品。
总结:
抽象工厂模式关注于一组相互关联的产品,而工厂方法模式关注于单一产品。抽象工厂模式的实现可能比较复杂,涉及多个产品族,而工厂方法模式通常相对简单,每个子类只负责一个产品。选择哪个模式取决于需求的复杂性和结构的设计。
抽象工厂模式在工厂模式的基础上扩展了一个维度,不仅关注单一产品的创建,还关注一组相关或相互依赖的产品族的创建。这些产品族通常在业务逻辑上有关联,它们可能共同构成一个完整的功能。
缺点总结:
在抽象工厂模式中,如果你想要增加一个新的产品,比如产品C,你需要在抽象工厂接口(或抽象类)中添加一个新的方法来创建该产品。然后,所有的具体工厂类都必须实现这个新方法,为产品C提供实现。这会导致两个问题:
-
修改抽象类或接口: 在这个例子中,你需要在
AbstractCreator中增加一个createProductC()方法,并且ConcreteFactory1 和ConcreteFactory2都必须实现这个方法。这违反了开闭原则,即系统应该对扩展开放,对修改关闭。 -
影响已有代码: 增加新方法会影响到所有已经实现了该抽象工厂的具体工厂类,即ConcreteFactory1 和ConcreteFactory2。这可能会导致许多现有的代码需要修改,因此它们与这个变化产生了依赖关系,即所谓的“有毒代码”。
这种情况下,每次需要增加一个新的产品时,都会引发一系列的修改,从而导致系统的脆弱性和不稳定性。这就是抽象工厂模式的一个局限性,特别是当产品族的变化比较频繁时,扩展性不如其他设计模式。
这也是为什么有时候推荐使用工厂方法模式,因为它对于新增产品更具有弹性,不会对已有的代码造成较大的影响。但抽象工厂模式的优势在于它能够同时创建一组相关的产品,适用于需要创建一组具有特定关联性的对象的情况。
但是也有优点,在添加新的产品族时,只需要新增对应的产品接口和实现,而不需要修改已有的工厂类和产品类。这符合开闭原则,允许易于扩展而不影响现有代码。
相关文章:
工厂模式 与 抽象工厂模式 的区别
工厂模式: // 抽象产品接口 interface Product {void showInfo(); }// 具体产品A class ConcreteProductA implements Product {Overridepublic void showInfo() {System.out.println("This is Product A");} }// 具体产品B class ConcreteProductB impl…...
安装虚拟机+安装/删除镜像
安装虚拟机 注意,官网可能无法登录,导致无法从官网下载,就自己去网上搜靠谱的下载,我用的16.2.3 删除镜像 Vm虚拟机怎么删除已经创建的系统?Vm虚拟机创建好之后iso删除方法 - 系统之家 (xitongzhijia.net) 安装镜像…...
MySQL的内置函数复合查询内外连接
文章目录 内置函数时间函数字符串函数数学函数其他函数 复合查询多表笛卡尔积自连接在where中使用子查询多列子查询在from中使用子查询 内连接外连接左外连接右外连接 内置函数 时间函数 函数描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳…...
操作系统(OS)与系统进程
操作系统(OS)与系统进程 冯诺依曼体系结构操作系统(Operator System)进程基本概念进程的描述(PCB)查看进程通过系统调用获取进程标示符(PID)通过系统调用创建进程(fork)进程状态&…...
防重复提交:自定义注解 + 拦截器(HandlerInterceptor)
防重复提交:自定义注解 拦截器(HandlerInterceptor) 一、思路: 1、首先自定义注解; 2、创建拦截器实现类(自定义类名称),拦截器(HandlerInterceptor); 3…...
Excel中将文本格式的数值转换为数字
在使用excel时,有时需要对数字列进行各种计算,比如求平均值,我们都知道应该使用AVERAGE()函数,但是很多时候结果却“不尽如人意”。 1 问题: 使用AVERAGE函数: 结果: 可以看到单元格左上角有个…...
uni-app开发小程序中遇到的map地图的点聚合以及polygon划分区域问题
写一篇文章来记录以下我在开发小程序地图过程中遇到的两个小坑吧,一个是点聚合,用的是joinCluster这个指令,另一个是polygon在地图上划分多边形的问题: 1.首先说一下点聚合问题,由于之前没有做过小程序地图问题&#…...
【笔记】软件测试的艺术
软件测试的心理学和经济学 测试是为发现错误而执行程序的过程,所以它是一个破坏性的过程,测试是一个“施虐”的过程。 软件测试的10大原则 1、测试用例需要对预期输出的结果有明确的定义 做这件事的前提是能够提前知晓需求和效果图,如果不…...
配置本地maven
安装maven安装包 修改环境变量 vim ~/.bash_profile export JMETER_HOME/Users/yyyyjinying/apache-jmeter-5.4.1 export GOROOT/usr/local/go export GOPATH/Users/yyyyjinying/demo-file/git/backend/go export GROOVY_HOME/Users/yyyyjinying/sortware/groovy-4.0.14 exp…...
C# 按钮的AcceptButton和CancelButton属性
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...
SMT贴片制造:专业、现代、智能的未来之选
在现代科技的快速发展下,SMT贴片制造作为电子元器件的核心工艺之一,正以其专业、现代和智能的特点成为未来的首选。 随着电子产品越来越小型化,传统的手工焊接已经无法满足高速、高精度、高稳定性的要求。而SMT贴片制造作为一种先进的表面贴…...
python sqlalchemy db.session 的commit()和colse()对session中的对象的影响
实验一:commit()之后查看stu的属性id,查看db.session是否改变 db_test.route("/db_test",methods["GET"]) def db_test():stuStuTest()stu.stu_age22stu.stu_name"nnannns"stu.stu_class11print("sessio…...
python读取图像小工具
一、和图像交互获得图像的坐标和像素值 import cv2 import numpy as np import signal import threading import timeif __name__ __main__:img cv2.imread(XXX,0)#读取图片font_face,font_scale,thicknesscv2.FONT_HERSHEY_SIMPLEX,0.5,1#鼠标交互def mouseHandler(event,x…...
【ES6】JavaScript中Reflect
Reflect是JavaScript中的一个内建对象,它提供了一组方法,用于对对象和函数进行操作和检查。这些方法与内建对象的方法非常相似,但具有更高的灵活性。 以下是Reflect对象的一些常用方法: 1、Reflect.apply(target, thisArgument,…...
Ajax + Promise复习简单小结simple
axios使用 先看看老朋友 axios axios是基于Ajaxpromise封装的 看一下他的简单使用 安装:npm install axios --save 引入:import axios from axios GitHub地址 基本使用 axios({url: http://hmajax.itheima.net/api/province}).then(function (result…...
WebDAV之π-Disk派盘 + 小书匠
小书匠是一款功能丰富,强大的知识管理工具。全平台覆盖,离线数据存储,自定义数据服务器,所见即所得的 markdown 编辑体验。 小书匠提供了多种实用的编辑模式,例如:栏编辑、双栏编辑、三栏编辑、全屏写作、全屏阅读等。并且该软件还提供了许多有用的扩展语法,比如Latex公…...
LTE ATTACH流程、PDN流程、PGW地址分配介绍
1、S-GW\P-GW选择 MME根据S-GW和P-GW的拓扑信息进行S-GW/P-GW的选择,在S-GW的候选序列和P-GW的候选序列中比较,寻找是否有合一的S-GW/P-GW,并且根据S-GW的优先级和权重信息进行排序,得到S-GW/P-GW的候选组。 2、SGW>PGW连接 PD…...
SQL sever中用户管理
目录 一、用户管理常见方法 二、用户管理方法示例 2.1. 创建登录账户: 2.1.1 检查是否创建账户成功: 2.2. 创建数据库用户: 2.2.1检查用户是否创建成功: 2.3. 授予权限: 2.3.1授予 SELECT、INSERT 和 U…...
linux————pxe网络批量装机
目录 一、概述 什么是pxe pxe组件 二、搭建交互式pxe装机 一、配置基础环境 二、配置vsftpd 三、配置tftp 四、准备pxelinx.0文件、引导文件、内核文件 一、准备pxelinux.0 二、准备引导文件、内核文件 五、配置dhcp 一、安装dhcp 二、配置dhcp 六、创建default文…...
处理时延降低24倍,联通云粒数据引擎优化实践
*作者:郑扬勇,云粒星河数据中台产品负责人 云粒智慧科技有限公司成立于 2018 年 6 月,是中国联通集团混改以来成立的首家合资公司,是中国智慧城市数智化建设者。一直以来,云粒智慧以数字化、智能化、集约化产品为核心&…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
