重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
在平常的学习和工作中,我们创建对象一般会直接用new,但是很多时候直接new会存在一些问题,而且直接new会让我们的代码变得非常繁杂,这时候就会巧妙的用到设计模式,平常我们通过力扣学习的算法可能并不会在我们工作中用到,但设计模式基本上我们所参加的每一个项目都会有。
今天来学习讲解一下工厂模式,这个也是我认为最常见的设计模式之一
1.什么是工厂模式
工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。 我们先从学校食堂窗口案例对工厂模式做个初步的了解:
- 没有工厂模式:在没有工厂模式的情况下,我们食堂窗口就类似于米饭,馒头,面条这些都需要我们自己创建,我们需要告诉窗口具体需要什么产品,然后自己创建
- 简单工厂模式:在简单工厂模式下,我们就不需要自己创建了,而是让食堂阿姨创建,但是简单工厂模式下只有一个工厂,也就是只有一个窗口,我们需要在这一个窗口选取我们所需要的食物
- 工厂方法模式:在工厂方法模式下,每一个食物就对应一个窗口,比如说分为米饭窗口,馒头窗口,面条窗口,我们需要什么仅需要去对应窗口买就可以了
- 抽象工厂模式:在抽象工厂模式下,每一个事物可能有多种组成成分,每一个窗口,可以生成多个食品以及食品组成成分,比如说有一个清真窗口,我们需要刀削面加牛肉,或者刀削面加羊肉,就仅需在这一个清真窗口把我们所需的参数传进去,就会我们生成对应的对象。
2.简单工厂模式
简单工厂模式的逻辑就是将定义一个创建对象的接口,将接口的创建和业务逻辑分开,我们需要修改逻辑仅需要去修改工厂里面的内容即可,降低耦合性。

上面就是简单工厂的uml图,简单工厂由于比较好理解一般来说仅有一个角色就是产品工厂,我们将需要的参数提交给简单工厂,简单工厂就会将产品生产出来。
代码实现:
产品类
abstract class food {public food(){}
}public class noodles extends food {public noodles () {System.out.println("制造-->noodles ");}
}
public class rice extends BMW{public rice (){System.out.println("制造-->rice ");}
}
工厂类:
public class Factory {public food createfood(int type) {switch (type) {case 1:return new rice();case 2:return new noodles();default:break;}return null;}
}
用户类:
public class Users{Factory factory = new Factory();food rice = factory.createfood(1);food noodles = factory.createfood(2);
}
上述之所以用1,2仅仅是为了方便写代码。
简单工厂模式的优缺点都很明显,有点就是解耦,缺点就是我们每次增加或者修改产品都需要去修改工厂类,如果项目规模特别大的话,这显然是无法接受的。
3 工厂方法模式
工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。

工厂方法一半分为四个角色
抽象工厂:每个具体工厂需要继承抽象工厂,一般来说用抽象类来实现
具体工厂:需要继承抽象工厂,生产具体产品,一般是具体生产逻辑
抽象产品:具体产品需要继承,有时候也可以没有
具体产品:我们所具体需要的对象
代码示例
产品类:
abstract class food{public food(){}
}
public class noodles extends food{public noodles () {System.out.println("制造-->noodles ");}
}
public class rice extends food{public rice (){System.out.println("制造-->rice ");}
}
工厂类:
interface Factoryfood {BMW createfood();
}public class Factorynoodles implements Factoryfood{@Overridepublic noodles createfood() {return new BMWnoodles();}}
public class Factoryrice implements Factoryfood {@Overridepublic rice createfood() {return new rice();}
}
用户类:
public class Customer {public static void main(String[] args) {Factoryrice factoryrice = new Factoryrice();rice = factoryrice.createrice();Factorynoodles factorynoodles = new Factorynoodles();noodles noodles = factorynoodles.createnoodles();}
}
4.抽象工厂模式
工厂方法模式中,一个工厂生成具体产品,但是正如我文章开头所说,我们所需要的可能不仅仅是一个产品,而是一个产品加某些组件,或者说有几个产品我们需要在一个工厂内生产。此时工厂方法模式就不再适用。
抽象工厂模式提供一个工厂生产多个组件+产品的功能,简单的说一个工厂生产的是一个产品族

抽象工厂 AbstractFactory:定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口。
具体工厂 ConcreteFactory:用于生产不同产品族,要创建一个产品,用户只需使用其中一个工厂进行获取,完全不需要实例化任何产品对象。
抽象产品 AbstractProduct:这是一个产品家族,每一个具体工厂都能够生产一整组产品。
具体产品 Product
抽象工厂相对来说没那么好理解,建议大家阅读一下下面的代码
代码示例:
产品类:
public interface Engine {} public class EngineA implements Engine{ public EngineA(){ System.out.println("制造-->EngineA"); }
}
public class EngineB implements Engine{ public EngineB(){ System.out.println("制造-->EngineB"); }
} public interface Aircondition {} public class AirconditionA implements Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); }
}
public class AirconditionB implements Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); }
}
工厂类
//创建工厂的接口
public interface AbstractFactory { public Engine createEngine();public Aircondition createAircondition();
} public class Factoryrice implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); }
}
//宝马523系列
public class Factorynoodles implements AbstractFactory { @Override public Engine createEngine() { return new EngineB(); } @Override public Aircondition createAircondition() { return new AirconditionB(); }
}
用户类:
public class Customer { public static void main(String[] args){ FactoryBMW320 factoryrice = new Factoryrice(); factoryBMW320.createEngine();factoryBMW320.createAircondition();FactoryBMW523 factorynoodles = new Factorynoodles(); factoryBMW523.createEngine();factoryBMW523.createAircondition();}
}
5.工厂模式小结
工厂模式主要是通过工厂这个对象来解耦,面对不同需求采用不同的工厂模式,切忌硬套代码模板
工厂模式应该是我们平常用到的最多的设计模式之一,但大家不要盲目去用,有很多用ifelse能够很简单解决的业务也可以不用工厂模式,不然到时候反而增加了我们的代码复杂度。
后面还会持续更新各种设计模式
相关文章:
重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
在平常的学习和工作中,我们创建对象一般会直接用new,但是很多时候直接new会存在一些问题,而且直接new会让我们的代码变得非常繁杂,这时候就会巧妙的用到设计模式,平常我们通过力扣学习的算法可能并不会在我们工作中用到…...
【C语言】结构体(四)
本篇重点是typedef关键字 一,是什么? typedef用来定义新的数据类型,通常typedef与结构体的定义配合使用。 简单来说就是取别名 ▶ struct 是用来定义新的数据类型——结构体 ▶ typedef是给数据类型取别名。 二,为什么…...
swift类方法为什么使用表派发?
直接上答案:因为表派发允许子类重写父类的方法,并在运行时根据对象的实际类型调用正确的方法实现。 什么是表派发? 首先我们先知道的是,swift当中函数的派发机制主要分为静态派发和动态派发。动态派发又分为表派发和消息派发。 …...
php实现AES/CBC/PKCS5Padding加密
接口文档 文档给过来的案例是java程序的,参照其思路,造一个php版本 构造aes对称加密 public static function encry($data){$data "要加密的数据";$key 你的256位密钥; // 密钥应该是16字节(128位),24字节…...
Anaconda3安装及使用
Anaconda3安装及使用 Linux中安装Anaconda31.安装 Anaconda32.配置环境变量3.验证是否成功 Conda环境和包管理1.Conda 环境初始化2.Conda Env 管理3.Conda 软件包管理 Linux中安装Anaconda3 下面是在Linux中安装Anaconda3-2021.05的教程,其他版本Anaconda更换名字即…...
Argon2-cffi与argon2-cffi-bindings:深入理解及其应用
Argon2-cffi与argon2-cffi-bindings的关系 在Python密码学领域,argon2-cffi和argon2-cffi-bindings是两个经常被提及的库。尽管它们的名字相似,但它们在实现和用途上有所不同。argon2-cffi是一个提供Argon2哈希算法的Python库,而argon2-cffi-…...
spring boot+jpa接入达梦数据库
文章目录 前言依赖配置对应的domain类和repository 前言 最近有一个新项目,由于信息安全等要求只能使用达梦数据库(dm8),之前从来没用过,特此开一个笔记记录一下spring bootjpa如何使用达梦数据库完成开发。 依赖 p…...
Vite构建,用NodeJS搭建一个简单的Vite服务
Vite 是一个现代的前端构建工具,由 Vue.js 作者尤雨溪创建。它主要用于开发和构建现代 JavaScript 应用,尤其是单页应用(SPA)。Vite 相比于传统的构建工具(如 Webpack)有几个显著的优势: 即时开…...
R语言机器学习论文(六):总结
文章目录 介绍参考文献介绍 本文采用R语言对来自进行数据描述、数据预处理、特征筛选和模型构建。 最后我们获得了一个能有效区分乳腺组织的随机森林预测模型,它的性能非常好,这意味着它可能拥有非常好的临床价值。 在本文中,我们利用R语言对来自美国加州大学欧文分校的B…...
python---面向对象---综合案例(4)
案例描述 实现加减乘法运算 # _*_ encoding:utf-8 _*_# 计算器, 实现一些基本的操作, 加减乘除运算, 以及打印结果操作# ------------------------------------代码1-------------------------------------- def jia(n1, n2):return n1 n2def jian(n1, n2):return n1 - n2de…...
如何参加华为欧拉考试?
华为欧拉考试主要针对的是华为欧拉(EulerOS/openEuler)操作系统的认证考试,这一认证体系旨在培养和认证具备基于欧拉操作系统进行企业级应用运行基础环境搭建、管理和调测能力的工程师以及云计算架构师。以下是对华为欧拉考试的详细介绍&…...
算法预刷题Day9:BM28 二叉树的最大深度
描述: 描述 求给定二叉树的最大深度, 深度是指树的根节点到任一叶子节点路径上节点的数量。 最大深度是所有叶子节点的深度的最大值。 (注:叶子节点是指没有子节点的节点。) 思路: 当前节点的最大高度 ma…...
exp_lr_scheduler理解
1. exp_lr_scheduler理解 这行代码定义了一个学习率调度器,用于动态调整训练过程中优化器的学习率。让我们分解并解释其含义: 1. exp_lr_scheduler 是什么? exp_lr_scheduler 是一个 学习率调度器(LR Scheduler),由 torch.optim.lr_scheduler.StepLR 创建,旨在按照预…...
Algorithm:河内之塔
1. 说明 河内之塔(Towers of Hanoi)是法国人 M.Claus(Lucas)于1883年从泰国带至法国的,河内为越战时北越的首都,即现在的胡志明市;1883年法国数学家 Edouard Lucas 曾提及这个故事,据…...
集中管理与实时审计:构建Linux集群(1300台服务器)日志平台的最佳实践
简介 随着企业IT基础设施的不断扩大,Linux服务器的数量也日益增多,传统的单机日志管理方式已无法满足对日志数据集中管理、审计和分析的需求。尤其是在大型集群环境中,如何高效地收集、存储和分析日志成为了一项重要的技术挑战。 背景 在实…...
在Scala中Array不可变的学习
package gjhs114import scala.collection.mutable.ArrayBuffer object Arrray114 {// 不可变数组:Array// def main(args: Array[String]): Unit {1 创建不可变数组// val arr1 Array(1,2,3)//2 访问.数组名(下标)。下标是从0开始到…...
vue3+vite 批量引入组件动态使用
import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…...
设计模式——方法链or流式接口
方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用,使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 (1)每个可链接的方法都返回对象自身的引用(通常是*this)…...
JAVA OPCUA 服务端开发,客户端连接会话监听和订阅事件监听
前言 关于使用milo开源库,开发opc ua服务器,有网友咨询如何设置服务端如何监听客户端的连接或断开事件,如何监听客户端发起订阅事件的代码实现,于是我完善了这部分的空缺整理整了这篇教程,希望能解决有同样需求,但是遇到困难的网友!因为milo没有官方文档的教程且网上详…...
pytest相关总结
1.pytest -v -s -v将测试用例名称和用例中的输出进行展示,将每条用例脚本的内容逐行进行结果展示; -s 参数是为了显示用例执行层级的打印信息 pytest使用总结笔记 - fengf233 - 博客园 2....
中国象棋智能辅助系统:视觉识别驱动的开源解决方案
中国象棋智能辅助系统:视觉识别驱动的开源解决方案 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi 在数字化对弈场景中,传统象棋辅…...
SpringAI与DeepSeek集成:兼容OpenAI API的流式对话实践
1. 环境准备与基础配置 在开始集成SpringAI与DeepSeek之前,我们需要确保开发环境满足以下要求: JDK 17或更高版本:Spring Boot 3.x系列需要JDK 17作为最低版本支持Spring Boot 3.4.2:这是当前推荐的稳定版本Maven或Gradle…...
如何通过Onekey技术解决Steam资源仓库的高效同步与版本控制难题
如何通过Onekey技术解决Steam资源仓库的高效同步与版本控制难题 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 问题:Steam资源管理的核心矛盾与行业痛点 在数字内容分发领域&#…...
终极指南:如何使用Skopeo与GitLab CI/CD实现Cloud Run镜像高效部署
终极指南:如何使用Skopeo与GitLab CI/CD实现Cloud Run镜像高效部署 【免费下载链接】skopeo Work with remote images registries - retrieving information, images, signing content 项目地址: https://gitcode.com/GitHub_Trending/sk/skopeo 在现代DevOp…...
从L2到Wing Loss:人脸关键点检测损失函数演进与实战解析
1. 人脸关键点检测与损失函数基础 人脸关键点检测是计算机视觉中的一项基础任务,需要精确定位眼睛、鼻子、嘴角等面部特征位置。这项技术在美颜相机、虚拟试妆、疲劳驾驶监测等场景中都有广泛应用。要让AI模型学会这项技能,关键在于设计合适的损失函数—…...
RevokeMsgPatcher防撤回工具深度指南:让重要消息不再消失的完整解决方案
RevokeMsgPatcher防撤回工具深度指南:让重要消息不再消失的完整解决方案 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: h…...
Python3.10开发环境搭建指南:Miniconda镜像简化部署流程
Python3.10开发环境搭建指南:Miniconda镜像简化部署流程 1. 为什么选择Miniconda-Python3.10 Python作为当今最流行的编程语言之一,版本管理一直是开发者面临的挑战。Miniconda-Python3.10镜像提供了一种轻量级解决方案,它能帮你࿱…...
KuiklyUI未来展望:2025路线图与技术演进趋势
KuiklyUI未来展望:2025路线图与技术演进趋势 【免费下载链接】KuiklyUI A Kotlin Multiplatform UI framework from Tencent TDS — high-performance, one codebase for six platforms, with dynamic delivery. 项目地址: https://gitcode.com/gh_mirrors/ku/Kui…...
别再手动配IP了!用NI-USRP Configuration Utility快速搞定USRP 2954与LabVIEW连接
告别手动配置:NI-USRP Configuration Utility 快速连接 USRP 2954 与 LabVIEW 全攻略 刚拿到 USRP 2954 设备时,许多工程师和研究人员的第一道坎往往不是复杂的信号处理算法,而是看似基础却令人头疼的网络配置问题。传统的手动 IP 配置方式不…...
一键生成爆炸图:Nano-Banana拆解引擎在产品说明书制作中的应用
一键生成爆炸图:Nano-Banana拆解引擎在产品说明书制作中的应用 1. 产品拆解可视化的行业痛点 在产品说明书、维修手册和教育材料的制作过程中,清晰展示产品内部结构和组件关系是至关重要的。传统方法通常面临三大挑战: 3D建模成本高&#…...
