当前位置: 首页 > 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…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)

+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么? 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元(地址),其核心含义与能力如下: 1. 核心定义 地址位宽:CPU或内存控制器用32位…...

大数据驱动企业决策智能化的路径与实践

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:数据驱动的企业竞争力重构 在这个瞬息万变的商业时代,“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...

HTML中各种标签的作用

一、HTML文件主要标签结构及说明 1. <&#xff01;DOCTYPE html> 作用&#xff1a;声明文档类型&#xff0c;告知浏览器这是 HTML5 文档。 必须&#xff1a;是。 2. <html lang“zh”>. </html> 作用&#xff1a;包裹整个网页内容&#xff0c;lang"z…...

Python_day48随机函数与广播机制

在继续讲解模块消融前&#xff0c;先补充几个之前没提的基础概念 尤其需要搞懂张量的维度、以及计算后的维度&#xff0c;这对于你未来理解复杂的网络至关重要 一、 随机张量的生成 在深度学习中经常需要随机生成一些张量&#xff0c;比如权重的初始化&#xff0c;或者计算输入…...