3、设计模式之工厂模式2(Factory)
一、什么是工厂模式
工厂模式属于创建型设计模式,它用于解耦对象的创建和使用。通常情况下,我们创建对象时需要使用new操作符,但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口,使得我们可以在不暴露对象创建逻辑的情况下创建对象。
二、工厂分类
工厂模式分为三种类型:简单工厂、方法工厂和抽象工厂,其本质就是对获取对象过程的抽象。
三、应用场景
3.1 生活场景
你需要一辆汽车,可以直接从工厂里提货,而不用关心它具体是怎么实现的
Hibernate换数据库只需要换方言和驱动就可以
3.2 java场景
BeanFactory:它是Spring
IoC容器的核心接口,通过读取配置文件或注解来创建Bean实例,并将它们注入到其他对象中。BeanFactory使用了工厂模式来隐藏具体的对象实例化过程,客户端只需要通过接口获取Bean对象,而不需要关心具体的实例化细节。
FactoryBean:是一种更高级别的工厂模式实现,用于创建特定类型的Bean对象。与普通的BeanFactory不同,FactoryBean的getObject()方法可以返回任意类型的对象实例,并且可以通过配置方式创建和管理实例。
Executors:提供了一系列的工厂方法来创建线程池(ThreadPoolExecutor)及其相关组件。
Charset:提供了一系列的静态工厂方法,如forName()、availableCharsets()等,用于创建Charset实例。

4.1 传统模式
在介绍工厂模式之前先来看看传统模式,以卖包子为例,如下:
//简单的制作流程
public BaoZi createBaoZi() {BaoZi baozi = new BaoZiImpl();//准备材料baozi.prepare();//制作包子baozi.make();//蒸包子baozi.braise();return baozi;
}
包子肯定有很多种类吧,那我们可以直接在上述代码中添加根据包子的种类生成不同类型的对象
/**
* 包子肯定有不同的馅:酸菜、豆沙、猪肉,那么他的材料、售价等方式也不同
* 我们可以直接在上述代码中,添加根据包子的不同种类生成不同的对象。
*/
public BaoZi createBaoZi(String type) {BaoZi baoZi = null;switch (type){case "suancai":baoZi=new SuanCaiBaoZi();break;case "dousha":baoZi=new DouShaBaoZi();break;case "pork":baoZi=new PorkBaoZi();break;default:throw new IllegalArgumentException("Invalid BaoZi Type");}//准备材料baoZi.prepare();//制作包子baoZi.make();//蒸包子baoZi.braise();return baoZi;
}
Test:
//1.传统模式@Testvoid traditonal(){SaleBaoZi saleBaoZi=new SaleBaoZi();//以猪肉包为例saleBaoZi.createBaoZi("pork");}
4.2 简单工厂模式
简单工程根据客户端的需求创建具体的实例,这种模式对调用者隐藏了实例创建的过程,也使得创建过程更加容易维护。
还是以卖包子为例,简单工厂模式实现如下:
/*** 2.简单工厂方法:希望能够创建一个对象,但创建过程比较复杂,希望对外隐藏这些细节*/
public class SimpleFactory {public static BaoZi createBaoZi(String type){BaoZi baoZi=null;switch (type){case "suancai":baoZi=new SuanCaiBaoZi("酸菜包");break;case "dousha":baoZi=new DouShaBaoZi("豆沙包");break;case "pork":baoZi=new PorkBaoZi("猪肉包");case "beef"://老板拓展业务了,新加了一个牛肉包类型的包子,那对于简单工厂模式而言,//于是就得修改源代码,那么就违反了ocp原则,假如新增100个?baoZi=new BeefBaoZi("牛肉包");break;default:throw new IllegalArgumentException("Invalid BaoZi Type");}return baoZi;}
}
Test:
//2.简单工厂模式@Testvoid simpleFactory(){//以猪肉包为例BaoZi pork = SimpleFactory.createBaoZi("pork");pork.prepare();pork.make();pork.braise();}
相比传统模式,从类图上就可以看出来,在sale和baozi中间又加了一层。
通过封装SimpleFactory这个类,我们将sale和baozi进行了解耦合。
4.3 方法工厂模式
简单工厂模式下,如果老板拓展业务了,加了一个牛肉种类的包子,就得在源码基础上修改,那么这就违背了开闭原则(ocp),即对扩展开放,对修改关闭。于是,为了解决这个问题,就又了工厂方法模式。
工厂方法模式是一种更加抽象的工厂模式,它将工厂的职责抽象为接口,由具体的工厂实现创建具体的对象。工厂方法模式弱化了工厂的实现,使得每个工厂只负责一个产品的创建。
抽象工厂MeAbStractFactory:
public interface MeAbstractFactory {BaoZi createBaoZi();
}
DouShaFactory:
//豆沙包
public class DouShaFactory implements MeAbstractFactory {@Overridepublic BaoZi createBaoZi() {return new DouShaBaoZi("豆沙包");}
}
PorkFactory:
//猪肉包
public class PorkFactory implements MeAbstractFactory {@Overridepublic BaoZi createBaoZi() {return new PorkBaoZi("猪肉包");}
}
BeefFactory:
//牛肉包
public class BeefFactory implements MeAbstractFactory {@Overridepublic BaoZi createBaoZi() {return new BeefBaoZi("牛肉包");}
Test:
//3.方法工厂模式@Testvoid methodFactory(){MeAbstractFactory factory=new PorkFactory();BaoZi pork = factory.createBaoZi();pork.prepare();pork.make();pork.braise();}
之前的SimpleFactory在createBaoZi中直接就new出来了,但在方法工厂中,我们将createBaoZi这个动作推迟到了MeAbStactFactory的子类(XXFactory)中才完成。
好处就是,比如后期要卖个羊肉包,我们直接编写个羊肉包类,然后实现MeAbstractFactory类就,实现它自己的功能,这样完全不用修改原来的代码了,也就解决了违反OCP原则的问题。
4.4 抽象工厂模式
抽象工厂模式是基于工厂方法模式的基础上进行的。在这种模式中,每一个工厂不再只负责一个产品的创建,而是负责一组产品的创建。抽象工厂模式将每个产品组都提取为一个接口,每个工厂都负责一个产品组。
假如老板的生意做大了,在北京开了个分店,并且不止卖包子,还卖蛋糕,那么该怎么拓展呢,很简单,只需要在抽象工厂类中新增创建蛋糕的抽象方法就行,如下:
AbstractFactory:public interface AbstractFactory {//制作包子BaoZi createBaoZi(String type);//制作蛋糕Cake createCake(String type);
}
BJFactory:
//北京分店
public class BJFactory implements AbstractFactory{@Overridepublic BaoZi createBaoZi(String type) {BaoZi baoZi=null;switch (type){case "beef":baoZi=new BJBeefBao("北京牛肉包");break;case "pork":baoZi=new BJPorkBao("北京猪肉包");default:break;}return baoZi;}@Overridepublic Cake createCake(String type) {Cake cake=null;switch (type){case "apple":cake=new BJAppleCake("北京苹果蛋糕");break;case "pear":cake=new BJPearCake("北京梨味蛋糕");default:break;}return cake;}
}
Test:
//4.抽象工厂模式
@Test
void abstractFactory(){AbstractFactory factory=new BJFactory();Cake apple = factory.createCake("apple");BaoZi pork = factory.createBaoZi("pork");apple.prepare();apple.make();apple.bake();apple.sale();pork.prepare();pork.make();pork.braise();pork.sale();
}
5.1 简单工厂模式
优点:
简单工厂模式实现简单,易于理解和使用; 可以对对象的创建进行集中管理,客户端和具体实现解耦。
缺点:工厂类负责创建所有对象,如果需要添加新类型的产品,则需要修改工厂类的代码,这违反了开闭原则; 工厂类职责过重,导致单一职责原则被破坏。
适用场景:工厂类负责创建的对象较少,客户端不需要知道对象的创建过程; 客户端需要根据传递的参数来获取对应的对象。
5.2 方法工厂模式
优点:
方法工厂模式具有良好的可扩展性,如果需要添加新类型的产品,只需要添加对应的工厂方法即可;
与简单工厂模式相比,方法工厂模式更符合开闭原则和单一职责原则。
缺点:需要客户端自行选择使用哪个工厂方法,不能像简单工厂模式那样直接传参获取对应对象,因此对客户端的编写有一定要求。 适用场景:
应用中需要创建的对象较少,但是需要具备良好的可扩展性; 客户端可以自行选择创建哪种对象。
5.3 抽象工厂
优点:
抽象工厂模式可以创建多个产品族的产品,这些产品之间有相互依赖或约束关系,有助于保持系统的一致性和稳定性;
客户端与具体产品解耦,通过产品族的方式进行管理。
缺点:抽象工厂模式增加了系统的抽象性和理解难度,不易于理解和修改; 新增产品族时需要修改工厂接口、工厂实现类和产品类,增加了系统的复杂性。
适用场景:系统需要一系列相互依赖或约束的产品; 客户端不需要知道具体产品的创建过程,只需要知道产品族即可。
相关文章:
3、设计模式之工厂模式2(Factory)
一、什么是工厂模式 工厂模式属于创建型设计模式,它用于解耦对象的创建和使用。通常情况下,我们创建对象时需要使用new操作符,但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口,使得我们可以在不暴露…...
npm、nodejs和vue之间关系和区别介绍
本文讲解npm、Node.js和Vue.js这三者之间的关系和区别,以及它们各自的特点。 首先,让我们来了解一下Node.js。 **Node.js** 是一个开源的服务器端运行环境,它允许开发者使用JavaScript来编写服务器端的代码。在传统的Web开发中&#…...
DM数据库安装(Windows)
先解压安装包 点击setup安装 下一步 勾选接受然后下一步 下一步 选择典型安装下一步 下一步 搜索DM数据库配置助手然后一直下一步 然后搜索DM管理工具 登录 登录成功 widows版本安装成功...
Python的asyncio 多线程
-- 多线程、进程、协程是什么就不讲了,(就是你理解的一边呼吸,一边看文章) 仅解决问题的话,下边两篇不用看, Python 中的 async await 概念-CSDN博客 再深一点的看这个 Python中的多线程、进程、协程、…...
【分类讨论】【解析几何】【 数学】【推荐】1330. 翻转子数组得到最大的数组值
作者推荐 视频算法专题 本文涉及知识点 分类讨论 解析几何 LeetCode1330. 翻转子数组得到最大的数组值 给你一个整数数组 nums 。「数组值」定义为所有满足 0 < i < nums.length-1 的 |nums[i]-nums[i1]| 的和。 你可以选择给定数组的任意子数组,并将该子…...
一文了解Spring的SPI机制
文章目录 一文了解Spring的SPI机制Java SPIServiceLoader Spring SPISpringboot利用Spring SPI开发starter 一文了解Spring的SPI机制 Java SPI SPI 全称 Service Provider Interface ,是 Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用…...
django根据时间(年月日)动态修改表名--方法一
方法一: 第一步:在models创建一个类,里边存放数据表中需要的字段,如下 class TemplateModel(models.Model):NowTime models.CharField(max_length5)name models.CharFiedld(max_length5)class Meta:abstract True # 基础类设…...
实现基本的登录功能
一、登录功能的前端处理过程 1、导入项目所需的图片和CSS等静态文件 参考代码存放client节点的/opt/code目录下 执行如下命令: [rootclient ~]# cp -r /opt/code/kongguan_web/src/assets/* /root/kongguan_web/src/assets/ 将参考代码中的css、icon、images等文…...
Java线程池实现原理及其在美团业务中的实践
随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流。使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器。 J.U.C提供的线程池:ThreadPoolExecutor类,帮助开发人员管理线程并方便地执行并行任务。了解并合理…...
让AI给你写代码(四)—— 初步利用LangChain Agent根据输入生成,保存,执行
要进一步提升智能编码助手的效率,我觉得需要做到两点 1) 进一步让主人聚焦于设计输入以及结果验证的循环 2) 进一步让智能编码助手聚焦于代码实现和程序流程(保存、打开,修订、执行、合并…) 正好接触到LLM…...
Flutter does not exist
Flutter does not exist 原因:Generated.config 配置文件内路径缺失 原因:Flutter SDK缺失 通过配置文件查到Flutter SDK在本地的存放位置FLUTTER_FRAMEWORK_DIR/Users/haijunyan/Documents/flutter/bin/cache/artifacts/engine/ios 真机所需…...
AIX上安装gcc和g++
AIX的iso镜像中没有gcc的软件包,需要我们自己下载,我们可以在 Index of /download/rpmdb/deplists/aix72 下载对应gcc和g版本的依赖文件deps 我们使用的是4.9.4版本的软件包 我们首先安装gcc,在http://www.oss4aix.org/download/everythi…...
js实现扫描线填色算法使用canvas展示
算法原理 扫描线填色算法的基本思想是:用水平扫描线从上到下扫描由点线段构成的多段构成的多边形。每根扫描线与多边形各边产生一系列交点。将这些交点按照x坐标进行分类,将分类后的交点成对取出,作为两个端点,以所填的色彩画水平…...
考研模拟面试-题目【攻略】
考研模拟面试-题目【攻略】 前言版权推荐考研模拟面试-题目前面的问题通用问题专业题数据结构计算机网络操作系统数据库网络安全 手写题数据结构操作系统计算机网络 代码题基础代码题其他代码题 后面的问题补充题目 最后 前言 2023-10-19 12:00:57 以下内容源自《考研模拟面试…...
Frostmourne - Elasticsearch源日志告警配置
简介 配置Frostmourne 接入Elasticsearch源进行日志匹配告警,并静默规则,告警消息发送到企业微信,告警信息使用Markdown。 部署安装教程查看: https://songxwn.com/frostmourne_install ELK 安装教程:https://songx…...
GPT出现Too many requests in 1 hour. Try again later.
换节点 这个就不用多说了,你都可以上GPT帐号了,哈…… 清除cooki 然后退出账号,重新登录即可...
python爬虫实战——小红书
目录 1、博主页面分析 2、在控制台预先获取所有作品页的URL 3、在 Python 中读入该文件并做准备工作 4、处理图文类型作品 5、处理视频类型作品 6、异常访问而被中断的现象 7、完整参考代码 任务:在 win 环境下,利用 Python、webdriver、JavaS…...
Linux信号机制
目录 一、信号的概念 二、定时器 1. alarm函数 2. setitimer函数 3.signal和sigaction函数 三、使用SIGCHLD信号实现回收子进程 一、信号的概念 概念:信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 。所有信号的产生及处理全部都是由内…...
区块链技术中的共识机制算法:以权益证明(PoS)为例
引言: 在区块链技术的演进过程中,共识机制算法扮演着至关重要的角色。除了广为人知的工作量证明(PoW)外,权益证明(Proof of Stake,PoS)也是近年来备受关注的一种共识算法。 …...
19113133262(微信同号)【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024)
【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024) 大会主题: (主题包括但不限于, 更多主题请咨询会务组苏老师) 区块链: 区块链技术和系统 分布式一致性算法和协议 块链性能 信息储存系统 区块链可扩展性 区块…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
