03-JAVA设计模式-工厂模式详解
工厂模式
工厂设计模式是一种创建型设计模式,它提供了一种封装对象创建过程的机制,将对象的创建与使用分离。
这种设计模式允许我们在不修改客户端代码的情况下引入新的对象类型。
在Java中,工厂设计模式主要有三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式
用来生成同一等级结构中的任意产品。
注:对增加新的产品需要修改已有的代码,这违背了面向对象设计原则中的开闭原则(对扩展开放,对修改关闭)
UML

实现代码
Animal.java
// 定义一个动物的接口
public interface Animal {// 接口中定义一个抽象的方法:叫声void makeSound();
}
Cat.java
// 定义一个实现类实现Animal接口
public class Cat implements Animal{// 猫属于动物:实现发出叫声的接口@Overridepublic void makeSound() {System.out.println("喵喵喵");}
}
Dog.java
// 定义一个实现类实现Animal接口
public class Dog implements Animal{// 狗属于动物:实现发出叫声的接口@Overridepublic void makeSound() {System.out.println("汪汪汪");}
}
SimpleAnimalFactory.java
// 定义一个简单工厂类用于创建动物
public class SimpleAnimalFactory {// 定义一个创建动物的方法用于生产不同的动物的静态方法public static Animal createAnimal(String type) {if ("Cat".equalsIgnoreCase(type)) {return new Cat();}else if ("Dog".equalsIgnoreCase(type)) {return new Dog();}else {return null;}}
}
TestClient.java
public class TestClient {public static void main(String[] args) {// 根据简单工厂创建不同的动物,执行动作// 生产一个CatAnimal cat = SimpleAnimalFactory.createAnimal("cat");cat.makeSound();// 生产一个DogAnimal dog = SimpleAnimalFactory.createAnimal("Dog");dog.makeSound();}
}
执行结果:

结论:
简单工厂好处在于,对于客户端调用时,我们不需要关心具体实现,只需要调用工厂方法,传入参数获取我们需要返回的结果即可。
但是对于同一个产品(动物),如果我们进行新增(猪),则必须要修改Factory中createAnimal(String type)方法。因此违背了开闭原则
工厂方法模式
用来生产同一等级结构中的固定产品。
支持增加任意产品,满足开闭原则,但设计相对于简单工厂复杂一些
UML

实现代码
Product.java
// 定义一个产品接口
public interface Product {//定义一个抽象的使用的方法void use();
}
ProductA.java
// ProductA实现Product接口
public class ProductA implements Product{@Overridepublic void use() {System.out.println("ProductA 使用了");}
}
ProductB.java
// ProductB实现Product接口
public class ProductB implements Product{@Overridepublic void use() {System.out.println("ProductB 使用了");}
}
ProductFactory.java
// 定义一个ProductFactory工厂接口
public interface ProductFactory {// 接口中定义一个创建Product的方法Product createProduct();
}
ProductAFactory.java
// 创建一个ProductA的工厂,实现ProductFactory接口,用于生产ProductA
public class ProductAFactory implements ProductFactory{@Overridepublic Product createProduct() {return new ProductA();}
}
ProductBFactory.java
// 创建一个ProductB的工厂,实现ProductFactory接口,用于生产ProductB
public class ProductBFactory implements ProductFactory{@Overridepublic Product createProduct() {return new ProductB();}
}
TestClient.java
public class TestClient {public static void main(String[] args) {// 创建ProductAProduct product1 = new ProductAFactory().createProduct();product1.use();// 创建ProductBProduct product2 = new ProductBFactory().createProduct();product2.use();}
}
执行结果:

从工厂方式模式,我们可以看出,我们可以任意增加同一产品,而不会影响到原来已有产品
(创建一个产品C继承Product接口,创建一个产品C的Factory类生产C,使用是通过相应Factory调用生产C即可)。
如果产品中新增一个方法,则所有实现了Product接口的方法都必须修改相应方法。
抽象工厂模式
用来生产不同产品族的全部产品。
对增加新的产品无能为力,支持增加产品族
UML

实现代码
Engine.java
// 定义发动机接口
public interface Engine {// 定义发动机 发动方法void run();// 定义发动机 停止方法void stop();
}
HighEndEngine.java
// 创建一个高端发动机实现发动机
public class HighEndEngine implements Engine{@Overridepublic void run() {System.out.println("高端发动机-跑的快");}@Overridepublic void stop() {System.out.println("高端发动机-刹车性能强");}
}
LowEndEngine.java
// 创建一个低端发动机实现发动机
public class LowEndEngine implements Engine{@Overridepublic void run() {System.out.println("低端发动机-跑的慢");}@Overridepublic void stop() {System.out.println("低端发动机-刹车性能弱");}
}
CarBody.java
// 定义一个车身接口
public interface CarBody {// 定义一个乘坐的方法void ride();
}
HighEndCarBody.java
// 创建一个高端车身实现车身
public class HighEndCarBody implements CarBody{@Overridepublic void ride() {System.out.println("高端车身-奢华-安全");}
}
LowEndCarBody.java
// 创建一个低端车身实现车身
public class LowEndCarBody implements CarBody{@Overridepublic void ride() {System.out.println("低端车身-朴素-看起来安全");}
}
Tyre.java
// 定义一个轮胎接口
public interface Tyre {// 定义轮胎转动的方法void run();
}
HighEndTyre.java
// 创建一个高端轮胎实现轮胎
public class HighEndTyre implements Tyre{@Overridepublic void run() {System.out.println("高端轮胎-太空材料-安全-耐磨");}
}
LowEndTyre.java
// 创建一个低端轮胎实现轮胎
public class LowEndTyre implements Tyre{@Overridepublic void run() {System.out.println("低端轮胎-普通材料-易磨损");}
}
CarFactory.java
// 定义Car的接口
public interface CarFactory {// 创建发动机Engine engine();// 创建车身CarBody carBody();// 创建轮胎Tyre tyre();
}
HighEndCarBody.java
// 高端汽车工厂实现汽车工厂
public class HighEndCarFactory implements CarFactory{@Overridepublic Engine engine() {return new HighEndEngine();}@Overridepublic CarBody carBody() {return new HighEndCarBody();}@Overridepublic Tyre tyre() {return new HighEndTyre();}
}
LowEndCarFactory.java
// 低端汽车工厂实现汽车工厂
public class LowEndCarFactory implements CarFactory{@Overridepublic Engine engine() {return new LowEndEngine();}@Overridepublic CarBody carBody() {return new LowEndCarBody();}@Overridepublic Tyre tyre() {return new LowEndTyre();}
}
TestClient.java
public class TestClient {public static void main(String[] args) {// 使用高端汽车工厂类 创建高端汽车HighEndCarFactory highEndCar = new HighEndCarFactory();highEndCar.engine().stop();highEndCar.carBody().ride();highEndCar.tyre().run();System.out.println("==========================");// 使用低端汽车工厂类 创建低端汽车LowEndCarFactory lowEndCar = new LowEndCarFactory();lowEndCar.engine().stop();lowEndCar.carBody().ride();lowEndCar.tyre().run();}
}
执行结果:

抽象工厂,不可以增加产品(比如:CarFactory一旦定下了,如果我们要新增新的部件则所有实现CarFactory的类都需实现该方法)。
但是抽象工厂,可以根据已有的接口,创建更多的产品族(比如:定义一个中端汽车工厂,调用高端发动机,低端轮胎,低端车身,等任意组合成新的Factory)
对比及应用场景
简单工厂模式
- 优点:
- 实现了对象的创建和使用的责任分割,客户端只需要传入正确的参数,就可以获取需要的对象,无需知道创建细节。
- 工厂类中有必要的判断逻辑,可以决定根据当前的参数创建对应的产品实例,客户端可以免除直接创建产品对象的责任。
- 缺点:
- 工厂类职责过重,如果产品种类增加,工厂类的代码会变得庞大且复杂,不利于维护。
- 简单工厂模式违背了开放封闭原则,因为每次增加新产品时,都需要修改工厂类的代码。
- 适用场景:
- 创建对象较少,且对象的创建逻辑不复杂时。
- 客户端不关心对象的创建过程,只关心使用对象时。
工厂方法模式
- 优点:
- 将对象的创建推迟到子类中进行,使得类的实例化更加灵活和可扩展。
- 降低了客户端与具体产品类之间的耦合度,客户端只需要知道对应的工厂,无需知道具体的产品类。
- 缺点:
- 增加了系统的抽象性和理解难度,需要引入额外的工厂接口和工厂类。
- 如果产品类较少,使用工厂方法模式可能会增加不必要的复杂性。
- 适用场景:
- 需要创建大量相似对象时,可以使用工厂方法模式来简化对象的创建过程。
- 当一个类需要由其子类来指定创建哪个对象时,可以使用工厂方法模式。
- 但实际开发中,简单工厂比工厂方法使用的更多
抽象工厂模式
- 优点:
- 提供了创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。
- 增加了系统的灵活性和可扩展性,可以通过更换不同的工厂来实现不同的产品族。
- 缺点:
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难。
- 如果产品族中的产品较少,使用抽象工厂模式可能会导致代码冗余和复杂性增加。
- 适用场景:
- 当需要创建一组相互关联或相互依赖的对象时,可以使用抽象工厂模式。
- 当一个系统需要独立地变化其创建的对象时,抽象工厂模式是一个很好的选择。
gitee源码
git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git
相关文章:
03-JAVA设计模式-工厂模式详解
工厂模式 工厂设计模式是一种创建型设计模式,它提供了一种封装对象创建过程的机制,将对象的创建与使用分离。 这种设计模式允许我们在不修改客户端代码的情况下引入新的对象类型。 在Java中,工厂设计模式主要有三种形式:简单工厂…...
百度文心大模型推理成本降至1% / 马斯克起诉OpenAI |魔法半周报
我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件🔥,更新AIGC的最新动态,生成相应的魔法简报,节省阅读时间👻 🔥资讯预览 百度文心大模型推理成本降至1%,与三星、荣耀等企业达成合作 马斯…...
Struts2的入门:新建项目——》导入jar包——》jsp,action,struts.xml,web.xml——》在项目运行
文章目录 配置环境tomcat 新建项目导入jar包新建jsp界面新建action类新建struts.xml,用来配置action文件配置Struts2的核心过滤器:web.xml 启动测试给一个返回界面在struts.xml中配置以实现页面的跳转:result再写个success.jsp最后在项目运行 配置环境 …...
git 标签功能操作以及回退
Git 标签功能允许开发者为特定的提交打上标签,以便后续能够方便地引用这些提交。标签通常用于标记重要的版本或里程碑,例如软件发布的版本号。与分支不同,标签指向的是固定的提交,一旦设置,就不能轻易更改。下面是一些…...
利用python实现文字转语音
代码如下: import pathlib import tkinter as tk import tkinter.ttk as ttk import tkinter.filedialog as filedialog import tkinter.messagebox as msgbox import pyttsx3class Application(tk.Tk):def __init__(self):super().__init__()self.title("文本…...
拾光坞N3 ARM 虚拟主机 i茅台项目
拾光坞N3 在Dcoker部署i茅台案例 OS:Ubuntu 22.04.1 LTS aarch64 cpu:RK3566 ram:2G 部署流程——》mysql——》java8——》redis——》nginx mysql # 依赖 apt update apt install -y net-tools apt install -y libaio* # 下载mysql wg…...
docker安装nacos,单例模式(standalone),使用mysql数据库
文章目录 前言安装创建文件夹"假装"安装一下nacos拷贝文件夹删除“假装”安装的nacos容器生成nacos所需的mysql表获取mysql-schema.sql文件创建一个mysql的schema 重新生成新的nacos容器 制作docker-compose.yaml文件查看网站 前言 此处有本人写得简易版本安装&…...
【运输层】传输控制协议 TCP
目录 1、传输控制协议 TCP 概述 (1)TCP 的特点 (2)TCP 连接中的套接字概念 2、可靠传输的工作原理 (1)停止等待协议 (2)连续ARQ协议 3、TCP 报文段的首部格式 1、传输控制协议…...
深入浅出 -- 系统架构之Keepalived搭建双机热备
Keepalived重启脚本双机热备搭建 ①首先创建一个对应的目录并下载keepalived安装包(提取码:s6aq)到Linux中并解压: [rootlocalhost]# mkdir /soft/keepalived && cd /soft/keepalived [rootlocalhost]# wget https://www.keepalived.…...
如何做好产业园运营?树莓集团:响应政府号召,规划,注重大局观
随着经济的发展和产业结构的调整,产业园区的建设和发展已经成为推动地方经济的重要力量。如何做好产业园运营,提高行业竞争力,现已成为了一个亟待解决的问题。树莓集团作为一家有着丰富产业园运营经验的企业,积极响应政府号召&…...
NIO与BIO
当谈到 Java 网络编程时,经常会听到两个重要的概念:BIO(Blocking I/O,阻塞 I/O)和 NIO(Non-blocking I/O,非阻塞 I/O)。它们都是 Java 中用于处理 I/O 操作的不同编程模型。 一、介…...
YOLOv5实战记录05 Pyside6可视化界面
个人打卡,慎看。 指路大佬:【手把手带你实战YOLOv5-入门篇】YOLOv5 Pyside6可视化界面_哔哩哔哩_bilibili 零、虚拟环境迁移路径后pip报错解决 yolov5-master文件夹我换位置后,无法pip install了。解决如下: activate.bat中修改…...
HTML5.Canvas简介
1. Canvas.getContext getContext(“2d”)是Canvas元素的方法,用于获取一个用于绘制2D图形的绘图上下文对象。在给定的代码中,首先通过getElementById方法获取id为"myCanvas"的Canvas元素,然后使用getContext(“2d”)方法获取该Ca…...
excel统计分析——多项式回归
参考资料:生物统计学 多项式回归属于单变量曲线回归,但其形式和求解方法与多元线性回归相似。多项式回归的数学模型为: 令,,,,则 由于X不可逆,两边同时乘以X得,ÿ…...
SQLyog连接数据库8.0版本解析错误问题解决方案
问题描述: 解决方案: alter userrootlocalhostidentified with mysql_native_password by 密码; 再次连接就可以了。...
【数据库】SQL简介
SQL(Structured Query Language,结构化查询语言)是一种用于管理关系型数据库管理系统(RDBMS)的标准化语言。它用于访问和操作数据库中的数据,执行各种任务,如插入、更新、删除和检索数据&#x…...
AWS入门实践-利用S3构建一个静态网站
使用Amazon S3托管静态网站是一个流行的选择,因为它简单、成本效益高,并且易于维护。静态网站由不含服务器端脚本的文件组成,如HTML、CSS和JavaScript文件。下面是使用S3托管静态网站的操作步骤: 如果大家没有AWS免费账号&#x…...
使用Linux strace追踪系统调用: 一个详细指南
使用Linux strace追踪系统调用: 一个详细指南 Linux strace是一个强大的命令行工具,用于监视和调试进程中发生的系统调用和信号。它对于系统管理员和开发人员来说是理解程序行为和解决问题的重要工具。 什么是strace? strace是一种跟踪运行中的进程执…...
python 笔记
文章目录 pdbpdb开始调试pythonpdb设置断点单步执行进入到函数的内部执行到下一个断点或程序结束调用栈查看命令查看当前函数调用堆栈向上一层函数查看调用堆栈查看源代码 importimport 用法 numpy导入numpy模块numpy常用函数np.argmaxnp.sum range生成连续序列生成不连续序列 …...
软考 系统架构设计师系列知识点之数据库基本概念(4)
接前一篇文章:软考 系统架构设计师系列知识点之数据库基本概念(3) 所属章节: 第6章. 数据库设计基础知识 第1节 数据库基本概念 6.1.3 数据库管理系统 DBMS(DataBase Management System,数据库管理系统&am…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
