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

工厂模式 与 抽象工厂模式 的区别

工厂模式:

// 抽象产品接口
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 是抽象产品接口,ConcreteProductAConcreteProductB 是具体的产品类。Creator 是抽象工厂类,ConcreteCreatorAConcreteCreatorB 是具体的工厂类,分别生产不同的产品。在场景类中,通过具体的工厂来创建不同的产品,而无需直接涉及具体产品的实现类。这就是工厂方法模式的正确用法。

抽象工厂模式:

// 抽象产品接口
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 是抽象工厂接口,ConcreteFactory1ConcreteFactory2 是具体工厂类,分别生产不同系列的产品。每个具体工厂类实现了创建一组相关产品的方法。这就是抽象工厂模式的示例。

区别:

抽象工厂模式(Abstract Factory Pattern)和工厂方法模式(Factory Method Pattern)是两种不同的设计模式,它们都属于创建型模式,用于创建对象。它们之间的区别在于抽象程度和用途。

  1. 抽象工厂模式

    • 抽象工厂模式用于创建一组相关或相互依赖的对象,这些对象通常属于不同的产品族。
    • 它包含一个抽象工厂接口,该接口声明了一组用于创建不同类型产品的抽象方法。每个具体工厂类实现了这些方法以创建特定产品族的对象。
    • 抽象工厂模式强调创建一组对象,通常涉及多个产品接口和多个产品实现类。
  2. 工厂方法模式

    • 工厂方法模式用于创建单一对象,但是通过子类来决定实例化哪个类。
    • 它包含一个抽象工厂基类(接口或抽象类),该基类声明了一个用于创建对象的抽象方法。每个具体工厂子类实现这个方法以返回特定的产品对象。
    • 工厂方法模式强调创建单一对象,每个工厂子类负责创建一种产品。

总结:

       抽象工厂模式关注于一组相互关联的产品,而工厂方法模式关注于单一产品。抽象工厂模式的实现可能比较复杂,涉及多个产品族,而工厂方法模式通常相对简单,每个子类只负责一个产品。选择哪个模式取决于需求的复杂性和结构的设计。

       抽象工厂模式在工厂模式的基础上扩展了一个维度,不仅关注单一产品的创建,还关注一组相关或相互依赖的产品族的创建。这些产品族通常在业务逻辑上有关联,它们可能共同构成一个完整的功能。

缺点总结:

在抽象工厂模式中,如果你想要增加一个新的产品,比如产品C,你需要在抽象工厂接口(或抽象类)中添加一个新的方法来创建该产品。然后,所有的具体工厂类都必须实现这个新方法,为产品C提供实现。这会导致两个问题:

  1. 修改抽象类或接口: 在这个例子中,你需要在AbstractCreator中增加一个createProductC()方法,并且ConcreteFactory1 和ConcreteFactory2都必须实现这个方法。这违反了开闭原则,即系统应该对扩展开放,对修改关闭。

  2. 影响已有代码: 增加新方法会影响到所有已经实现了该抽象工厂的具体工厂类,即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 月,是中国联通集团混改以来成立的首家合资公司,是中国智慧城市数智化建设者。一直以来,云粒智慧以数字化、智能化、集约化产品为核心&…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes&#xff0…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 ​二、实现思路 总体思路: 用户通过Gradio界面上…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...