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

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得,&#xff…...

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…...

Connect to Oracle Database with JDBC Driver

1. Overview The Oracle Database is one of the most popular relational databases. In this tutorial, we’ll learn how to connect to an Oracle Database using a JDBC Driver. 2. The Database To get us started, we need a database. If we don’t have access to …...

vLLM-v0.17.1保姆级教程:SSH中查看vLLM实时请求队列与Pending统计

vLLM-v0.17.1保姆级教程:SSH中查看vLLM实时请求队列与Pending统计 1. vLLM框架简介 vLLM是一个专注于大语言模型(LLM)推理和服务的高性能库,它的设计目标是让开发者能够轻松部署和管理大规模语言模型。这个项目最初由加州大学伯克利分校的天空计算实验…...

别再让时钟信号‘跑偏’了!手把手教你理解ADC中DCC电路的设计要点

高速ADC设计中的时钟占空比校正实战指南 时钟信号就像ADC系统的心跳,每一次跳动都决定着数据采样的精准度。当这个"心跳"变得不规律时,整个系统的性能就会大打折扣。在高速ADC设计中,时钟占空比失真是一个常见却又容易被忽视的问题…...

3步打造高效Fortran开发环境:VSCode Modern Fortran扩展深度解析

3步打造高效Fortran开发环境:VSCode Modern Fortran扩展深度解析 【免费下载链接】vscode-fortran-support Fortran language support for Visual Studio Code 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-fortran-support 在科学计算和高性能计算领…...

Mi-Create终极指南:三步快速创建专属小米手表表盘

Mi-Create终极指南:三步快速创建专属小米手表表盘 【免费下载链接】Mi-Create Unofficial watchface creator for Xiaomi wearables ~2021 and above 项目地址: https://gitcode.com/gh_mirrors/mi/Mi-Create 想要为你的小米手表打造独一无二的个性化表盘吗&…...

实验结果与分析篇 | 本科/硕士必备,一文搞定实验结果与分析部分!基于改进 ConvNeXt 的农作物病虫害识别系统

前言 “代码跑通了,论文怎么写?”,这恐怕是无数 CV 算法/人工智能萌新在面对毕设或期刊投稿时最大的痛。纯缝合模型容易被拒(看你写作能力了),实验分析写成了干巴巴的报流水账,缺乏深度的理论支…...

从VGG到ResNet:为什么说‘残差块’是深度学习模型‘卷’层数的救命稻草?

从VGG到ResNet:残差连接如何重塑深度神经网络的设计哲学 2014年ImageNet竞赛上,VGGNet凭借其规整的3x3卷积堆叠结构一举夺魁,将图像识别准确率提升到新高度。正当整个计算机视觉领域沉浸在"更深就一定更好"的乐观情绪中时&#xff…...

【Java】UTF-8变长编码及其3字节存储奥秘

UTF-8 是一种变长编码,一个字符可能由 1 到 4 个字节组成。 解码时(将字节数组转回 String),计算机并不需要“猜”或者去查表,因为长度信息本身就包含在字节的“头部”里。这就是 UTF-8 设计的精妙之处:它是…...

iMeta入选新锐期刊分区表生物学1区Top

2026年3月24日,2026年新锐期刊分区表正式发布。iMeta被评选为生物学1区Top期刊,标志着iMeta期刊学术声誉与影响力持续提升。自创刊以来,iMeta的每一步成长都离不开期刊编委、审稿专家及广大同行的鼎力支持。未来,iMeta将再接再厉&…...

OpenClaw自动化测试:百川2-13B-4bits量化模型在重复任务中的稳定性

OpenClaw自动化测试:百川2-13B-4bits量化模型在重复任务中的稳定性 1. 测试背景与目标 最近在尝试用OpenClaw搭建一个本地自动化工作流时,发现一个关键问题:当AI需要反复执行相同任务时,模型响应的稳定性会直接影响自动化效果。…...