01 设计模式-创造型模式-工厂模式

  • 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,它提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。

  • 工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。

  • 通过使用工厂模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。

设计模式,最近持续更新中,如需要请关注

如果你觉得我分享的内容或者我的努力对你有帮助,或者你只是想表达对我的支持和鼓励,请考虑给我点赞、评论、收藏。您的鼓励是我前进的动力,让我感到非常感激。

文章目录

  • 1 概要
  • 2 实现
  • 3 Demo代码
  • 4 开发案例
    • 4.1 算法执行服务里,不同的任务数据来源不同,执行脚本类型不同,结果处理不同,使用工厂模式
    • 4.2 网络还原时,不同的采集数据,解析处理方式不同

1 概要

意图
定义一个创建对象的接口,让其子类决定实例化哪一个具体的类。工厂模式使对象的创建过程延迟到子类。

主要解决
接口选择的问题。

何时使用
当我们需要在不同条件下创建不同实例时。

如何解决
通过让子类实现工厂接口,返回一个抽象的产品。

关键代码
对象的创建过程在子类中实现。

应用实例

  1. 汽车制造:你需要一辆汽车,只需从工厂提货,而不需要关心汽车的制造过程及其内部实现。
  2. Hibernate:更换数据库时,只需更改方言(Dialect)和数据库驱动(Driver),即可实现对不同数据库的切换。

优点

  1. 调用者只需要知道对象的名称即可创建对象。
  2. 扩展性高,如果需要增加新产品,只需扩展一个工厂类即可。
  3. 屏蔽了产品的具体实现,调用者只关心产品的接口。

缺点
每次增加一个产品时,都需要增加一个具体类和对应的工厂,使系统中类的数量成倍增加,增加了系统的复杂度和具体类的依赖。

使用场景

  1. 日志记录:日志可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志的位置。
  2. 数据库访问:当用户不知道最终系统使用哪种数据库,或者数据库可能变化时。
  3. 连接服务器的框架设计:需要支持 “POP3”、“IMAP”、“HTTP” 三种协议,可以将这三种协议作为产品类,共同实现一个接口。
  4. 在算法执行服务中,每个任务需要处理的数据来源不同,根据数据类型创建对应的数据出来handle类,不用关心handle里的内部处理逻辑

注意事项
工厂模式适用于生成复杂对象的场景。如果对象较为简单,通过 new 即可完成创建,则不必使用工厂模式。使用工厂模式会引入一个工厂类,增加系统复杂度。

结构
工厂模式包含以下几个主要角色:

  • 抽象产品(Abstract Product):定义了产品的共同接口或抽象类。它可以是具体产品类的父类或接口,规定了产品对象的共同方法。
  • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
  • 抽象工厂(Abstract Factory):声明了创建产品的抽象方法,可以是接口或抽象类。它可以有多个方法用于创建不同类型的产品。
  • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。

2 实现

我们将创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory。

FactoryPatternDemo 类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。
请添加图片描述

3 Demo代码

在这里插入图片描述
Shape

/*** 公共接口*/
public interface Shape {void draw();
}

Circle

/*** 圆形,形状的实现类*/
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

Rectangle

/*** 矩形,形状的实现类*/
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}

Square

/*** 方形,形状的实现类*/
public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}

ShapeFactory

/*** 形状工厂类【根据不同的参数创建对应的实例】*/
public class ShapeFactory {//使用 getShape 方法获取形状类型的对象public Shape getShape(String shapeType) {if (shapeType == null) {return null;}if (shapeType.equalsIgnoreCase("CIRCLE")) {return new Circle();} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {return new Rectangle();} else if (shapeType.equalsIgnoreCase("SQUARE")) {return new Square();}return null;}
}

FactoryPatternDemo

/***    总结:用来根据不同的参数创建对象*/
public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory = new ShapeFactory();//获取 Circle 的对象,并调用它的 draw 方法Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取 Rectangle 的对象,并调用它的 draw 方法Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取 Square 的对象,并调用它的 draw 方法Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();}
}

效果
在这里插入图片描述

4 开发案例

4.1 算法执行服务里,不同的任务数据来源不同,执行脚本类型不同,结果处理不同,使用工厂模式

请添加图片描述
说明:

  • TaskAbstractFactory命名成抽象工厂,可以创建出来DataSetHandle工厂,ScriptExecuteHandle工厂,ResultHandle工厂,但是实现时,时间关系,简化成简单工厂模式。
  • 工厂返回的对象,每次都是新创建出来的,因为这些handle每次创建初始化的参数是不同的,和下面的第二个案例有所不同

在这里插入图片描述

工厂类

/*** 任务抽象工厂类,创建各种处理类* @since 2023 -10-08 16:13*/
public class TaskAbstractFactory {private static final Logger LOGGER = LoggerFactory.getLogger(TaskAbstractFactory.class);/*** Gets script execute handle.** @param scriptParam the script param* @param algoId the algo id* @return the script execute handle*/public static ScriptExecuteHandle getScriptExecuteHandle(ScriptParam scriptParam, String algoId) {if (Constants.ScriptType.PYTHON.equals(scriptParam.getScriptType()) || Constants.ScriptType.PYTHON3.equals(scriptParam.getScriptType())) {return new PythonScriptExecuteHandle(scriptParam);} else {LOGGER.error("The algorithm type is not supported. algoId: {} ,scriptType: {} ", algoId,scriptParam.getScriptType());throw new CommonServiceException(AIModelError.ALGO_TYPE_NOT_SUPPORTED);}}/*** Gets data set handle list.** @param dataSets the data sets* @return the data set handle list*/public static List<DataSetHandle> getDataSetHandleList(List<InputDataSource> dataSets) {ArrayList<DataSetHandle> dataSetHandleList = new ArrayList<>(10);for (InputDataSource inputDataSource : dataSets) {dataSetHandleList.add(getDataSetHandle(inputDataSource));}return dataSetHandleList;}/*** Gets data set handle.** @param inputDataSource the input data source* @return the data set handle*/public static DataSetHandle getDataSetHandle(InputDataSource inputDataSource) {if (Constants.DataSourceType.MINIO_FILE.equalsIgnoreCase(inputDataSource.getDatatype())) {DataSetHandle dataSetHandle = new S3DataSetHandle(inputDataSource.getDataSourceInfo(),inputDataSource.getDataSourceConfig());// 进行数据源校验dataSetHandle.checkDataSource();return dataSetHandle;} else if (Constants.DataSourceType.HDFS_FILE.equalsIgnoreCase(inputDataSource.getDatatype())) {DataSetHandle dataSetHandle = new HdfsDataSetHandle(inputDataSource.getDataSourceInfo(),inputDataSource.getDataSourceConfig());// 进行数据源校验dataSetHandle.checkDataSource();return dataSetHandle;} else {LOGGER.error("The data source type is not supported. datatype: {} ", inputDataSource.getDatatype());throw new CommonServiceException(AIModelError.DATA_TYPE_NOT_SUPPORTED);}}/*** Gets result handle.** @param calculateParam the calculate param* @param scriptParam the script param* @return the result handle*/public static ResultHandle getResultHandle(CalculateParam calculateParam, ScriptParam scriptParam) {// 【预留】 设置结果集存放的数据源。目前所有的算法都有数据集,取数据集的第一个数据源作为结果上传的数据源OutputDataSource outputDataSource = getOutDataSource(calculateParam.getDataSets().get(0));if (Constants.CustomizedAlgoId.POTENTIAL_GUEST_ALGO_ID.equals(calculateParam.getAlgoId())) {// 定制化的处理方式,需要走特有的处理方式。此类算法,只能提前预置后return new PotentialGuestResultHandle(scriptParam, outputDataSource);} else {// 任务结果走默认处理方式,此类算法可以通过算法管理界面可以添加return new ResultHandle(scriptParam, outputDataSource);}}private static OutputDataSource getOutDataSource(InputDataSource inputDataSource) {return new OutputDataSource(inputDataSource.getDatatype(), inputDataSource.getDataSourceConfig());}}

使用

    public TaskEntity(TaskInfo taskInfo, CalculateParam calculateParam, String algoPackDir, String localFileDir) {this.scriptParam = getScriptParam(calculateParam, algoPackDir, localFileDir);this.taskInfo = taskInfo;this.shellParamHandle = TaskAbstractFactory.getScriptExecuteHandle(scriptParam, calculateParam.getAlgoId());this.dataSetHandleList = TaskAbstractFactory.getDataSetHandleList(calculateParam.getDataSets());this.resultHandle = TaskAbstractFactory.getResultHandle(calculateParam, scriptParam);}

其他说明
设计是工厂创建实例的是子类,返回的是父类。多态的体现。同事父类有默认方法,子类是对父类的扩展, 或者重写。如下:
DataSetHandle

/*** 数据集处理父类* @since 2023 -09-15 15:35*/
public abstract class DataSetHandle {private static final Logger LOGGER = LoggerFactory.getLogger(DataSetHandle.class);/*** The Data source info.*/protected String dataSourceInfo;/*** The Data source config.*/protected String dataSourceConfig;/*** Instantiates a new Data set handle.** @param dataSourceInfo the data source info* @param dataSourceConfig the data source config*/public DataSetHandle(String dataSourceInfo, String dataSourceConfig) {this.dataSourceInfo = dataSourceInfo;this.dataSourceConfig = dataSourceConfig;}/*** Check data source.*/public void checkDataSource() {// 对参数的json格式进行校验if (!MyStringUtil.checkJson(dataSourceInfo)) {LOGGER.error("dataSourceInfo json format error.");throw new CommonServiceException(AIModelError.PARAM_ERROR, "dataSourceInfo json format error.");}if (StringUtils.isNotEmpty(dataSourceConfig) && !MyStringUtil.checkJson(dataSourceConfig)) {LOGGER.error("dataSourceConfig json format error.");throw new CommonServiceException(AIModelError.PARAM_ERROR, "dataSourceConfig json format error.");}}/*** Handle data.** @param taskId the task id* @param localFileDir the local file dir*/public abstract void handleData(String taskId, String localFileDir);}

S3DataSetHandle

/*** S3或者minio类型的数据集处理类* @since 2023 -09-15 15:35*/
public class S3DataSetHandle extends DataSetHandle {private static final Logger LOGGER = LoggerFactory.getLogger(S3DataSetHandle.class);/*** Instantiates a new S 3 data set handle.** @param dataSourceInfo the data source info* @param dataSourceConfig the data source config*/public S3DataSetHandle(String dataSourceInfo, String dataSourceConfig) {super(dataSourceInfo, dataSourceConfig);}/*** Check data source.*/@Overridepublic void checkDataSource() {// 1 父类进行参数json格式的校验super.checkDataSource();// 2 具体子类,进行特性校验List<S3DataSourceInfo> s3DataSourceList = JSON.parseArray(dataSourceInfo, S3DataSourceInfo.class);for (S3DataSourceInfo s3DataSource : s3DataSourceList) {// 目前S3,仅支持zip文件if (!Constants.FileType.ZIP.equalsIgnoreCase(s3DataSource.getFileType())) {LOGGER.error("The file type is not supported. fileType:{}", s3DataSource.getFileType());throw new CommonServiceException(AIModelError.PARAM_ERROR,"The file type is not supported. fileType: " + s3DataSource.getFileType());}if (StringUtils.isEmpty(s3DataSource.getFileId()) || StringUtils.isEmpty(s3DataSource.getStoreDirName())) {LOGGER.error("fileId and storeDirName cannot be empty.");throw new CommonServiceException(AIModelError.PARAM_ERROR, "fileId and storeDirName cannot be empty.");}}}/*** Handle data.** @param taskId the task id* @param localFileDir the local file dir*/@Overridepublic void handleData(String taskId, String localFileDir) {// 1 获取配置S3DataSourceConfig s3DataSourceConfig = JSON.parseObject(dataSourceConfig, S3DataSourceConfig.class);// 2 初始化S3客户端S3ClientUtils s3ClientUtils = S3ClientUtils.getInstance(s3DataSourceConfig);for (S3DataSourceInfo s3DataSourceInfo : JSON.parseArray(dataSourceInfo, S3DataSourceInfo.class)) {InputStream s3InputStream = null;try {// 3 获取数据流s3InputStream = s3ClientUtils.download(s3DataSourceConfig.getBucketName(),s3DataSourceInfo.getFileId());// 4 将文件保存在本地磁盘saveFileToLocal(s3InputStream, s3DataSourceInfo, taskId, localFileDir + taskId);} finally {MyIOUtils.closeInputStream(s3InputStream);}}}
}

4.2 网络还原时,不同的采集数据,解析处理方式不同

说明:

  • 创建对象由spring类管理,创建出来的对象是单例的,这个案例1有所不同,案例1,每个类初始化的参数不同。这个案例对象初始化方式一样,只是处理逻辑不同。
  • 在vimpim对象是,因为参数不同所有每次都需要new

工厂类:

/*** The type Ods process factory.** @since 2024 -06-11 10:54*/
@Slf4j
@Service
public class OdsProcessFactory {private static final List<VimPimModelDto> VIM_PIM_MODEL_V2_LIST = new ArrayList<>();private static final String VIM_PIM_MODEL_V2_FILE_PATH = "2.json";private static final List<String> VIM_PIM_MODEL_V2_WHITE_LIST = Arrays.asList();private static final List<VimPimModelDto> VIM_PIM_MODEL_V3_LIST = new ArrayList<>();private static final String VIM_PIM_MODEL_V3_FILE_PATH = "3.json";private static final List<String> VIM_PIM_MODEL_V3_WHITE_LIST = Arrays.asList();/*** The Data source.*/@Resource(name = "gauss")DataSource dataSource;@Autowiredprivate VimPimRepository vimPimRepository;@Autowiredprivate VnfMaeCnDataProcessDomainService vnfMaeCnDataProcessDomainService;@Autowiredprivate VnflocLcmDataProcessDomainService vnflocLcmDataProcessDomainService;static {// 初始化模型数据initModel(VIM_PIM_MODEL_V2_FILE_PATH, VIM_PIM_MODEL_V2_WHITE_LIST, VIM_PIM_MODEL_V2_LIST);initModel(VIM_PIM_MODEL_V3_FILE_PATH, VIM_PIM_MODEL_V3_WHITE_LIST, VIM_PIM_MODEL_V3_LIST);}private static void initModel(String vimPimModelFilePath, List<String> vimPimModelWhiteList,List<VimPimModelDto> vimPimModelList) {}/*** Gets ods process service.** @param taskDto the task dto* @param dataFormat the data format* @return the ods process service*/public DataProcessDomainService getOdsProcessService(CollectionTaskDto taskDto, int dataFormat) {if (OdsParseConstants.OdsDataFormat.VNF_MAECN == dataFormat|| OdsParseConstants.OdsDataFormat.NIC_DSP == dataFormat) {return vnfMaeCnDataProcessDomainService;} else if (OdsParseConstants.OdsDataFormat.VIM_OV2 == dataFormat|| OdsParseConstants.OdsDataFormat.PIM_OV2 == dataFormat) {return getVimPimDataProcessV2DomainService();} else if (OdsParseConstants.OdsDataFormat.VIM_OV3 == dataFormat|| OdsParseConstants.OdsDataFormat.PIM_OV3 == dataFormat) {return getVimPimDataProcessV3DomainService();} else if (OdsParseConstants.OdsDataFormat.VNFLOC_LCM == dataFormat) {return vnflocLcmDataProcessDomainService;} else {// 采集来的数据格式不支持log.warn("Incorrect data dataFormat. taskId:{}, tasksSn:{}, dataFormat:{} ", taskDto.getTaskId(),taskDto.getTaskSn(), dataFormat);}return null;}public VimPimDataProcessV2DomainService getVimPimDataProcessV2DomainService() {return new VimPimDataProcessV2DomainService(VIM_PIM_MODEL_V2_LIST, dataSource, vimPimRepository);}public VimPimDataProcessV3DomainService getVimPimDataProcessV3DomainService() {return new VimPimDataProcessV3DomainService(VIM_PIM_MODEL_V3_LIST, dataSource, vimPimRepository);}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/448698.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【wpf】06 HTTP/HTTPS请求的相关设计

这篇文章主要记录在用wpf开发应用程序从服务器端获取数据之前的准备工作。 1 HTTP标头信息 首先需要说明一下HTTP标头的信息&#xff0c;在使用wpf发送请求的过程中需要设置部分信息&#xff0c;大部分暂时用不到。 HTTP头信息 头信息由“键&#xff1a;值”组成。它们描述…

语音识别与语音控制

硬件平台 机器硬件&#xff1a;OriginBot(导航版/视觉版)PC主机&#xff1a;Windows&#xff08;>10&#xff09;/Ubuntu(>20.04)扩展硬件&#xff1a;X3语音版 运行案例 首先进入OriginBot主控系统&#xff0c;运行一下指令。请注意&#xff0c;部分操作OriginBot内暂…

第三课:python学习之安装pygame

首先确定自己的python已经将环境变量配置完成 第二步&#xff1a;敲击python命令看环境变量是否配置成功 第三步&#xff1a;敲击命令pip可以查看pip下有很多的命令&#xff0c;都有提示 第四步&#xff1a;我们开始安装pygame,我们使用pip install pygame命令进行安装 第五步…

【优选算法】——双指针(上篇)!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C刷题算法总结&#x1f516;克心守己&#xff0c;律己则安 目录 前言&#xff1a;双指针 1. 移动零&#xff08;easy&#xff09; 2. 复写零&#xff08;easy&#xff09; 3…

Run the FPGA VI 选项的作用

Run the FPGA VI 选项的作用是决定当主机 VI 运行时&#xff0c;FPGA VI 是否会自动运行。 具体作用&#xff1a; 勾选 “Run the FPGA VI”&#xff1a; 当主机 VI 执行时&#xff0c;如果 FPGA VI 没有正在运行&#xff0c;系统将自动启动并运行该 FPGA VI。 这可以确保 FPG…

基于SpringBoot+Vue+uniapp的个人财务系统的详细设计和实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

【C++进阶】set的使用

1. 序列式容器和关联式容器 前面&#xff0c;我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间⼀般没有紧…

《深度学习》OpenCV LBPH算法人脸识别 原理及案例解析

目录 一、LBPH算法 1、概念 2、实现步骤 3、方法 1&#xff09;步骤1 • 缩放 • 旋转和平移 2&#xff09;步骤2 二、案例实现 1、完整代码 1&#xff09;图像内容&#xff1a; 2&#xff09;运行结果&#xff1a; 一、LBPH算法 1、概念 在OpenCV中&#xff0c;L…

【Spring AI】Java实现类似langchain的第三方函数调用_原理与详细示例

Spring AI 介绍 &#xff1a;简化Java AI开发的统一接口解决方案 在过去&#xff0c;使用Java开发AI应用时面临的主要困境是没有统一且标准的封装库&#xff0c;导致开发者需要针对不同的AI服务提供商分别学习和对接各自的API&#xff0c;这增加了开发难度与迁移成本。而Sprin…

vue elementui table编辑表单时,弹框增加编辑明细数据

需求: 前端进行新增表单时&#xff0c;同时增加表单的明细数据。明细数据部分&#xff0c;通过弹框方式增加或者编辑。 效果图&#xff1a; 代码&#xff1a; <!-- 新增主表弹窗 Begin --><el-dialog:title"titleInfo"top"5vh"centerwidth"…

软件安全漏洞挖掘: 基础知识和概念

1. 软件漏洞原理和漏洞检测方法 文章目录 1. 软件漏洞原理和漏洞检测方法1. 漏洞披露2. 漏洞定义和分类1. 漏洞的定义2. 漏洞的分类3. 漏洞检测方法常见方法1. 程序切片2. 形式化方法1. 符号执行3. 污点分析污点分析步骤/流程*污点分析流程的详细介绍1. 识别source和sink点2. 污…

SpringBoot项目:mybatis升级mybatis-plus

替换依赖修改sqlSessionFactory bean分页插件不生效问题记录 1.替换依赖&#xff1a; 将原来的mybatis整合springboot的依赖去掉&#xff0c;替换成mybatis-plus <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter…

idea2024年版本

最简单安装2024.2版本idea 内带安装教程 ** 下载链接&#xff1a;https://pan.quark.cn/s/ab24afbaa43f 提取码&#xff1a;KHrq

blender分离含有多个动作的模型,并导出含有材质的fbx模型

问题背景 笔者是模型小白&#xff0c;需要将网络上下载的fbx模型中的动作&#xff0c;分离成单独的动作模型&#xff0c;经过3天摸爬滚打&#xff0c;先后使用了blender&#xff0c;3d max&#xff0c;unity&#xff0c;最终用blender完成&#xff0c;期间参考了众多网络上大佬…

用jsp以及servlet实现获取图片验证码

jsp文件 <% page contentType"text/html;charsetUTF-8" language"java" %> <% request.setCharacterEncoding("UTF-8"); %> <% response.setCharacterEncoding("UTF-8"); %> <html> <head><title&g…

【更新】中国地区粮食播种、粮食产量、灾害等数据(1990-2023年)

数据为中国地区粮食播种、粮食产量、灾害等数据&#xff0c;包括369个指标&#xff0c;各类农作物播种面积、粮食产量、牲畜饲养、受灾面积等。这些指标综合反映了中国农业生产、粮食安全的相关情况 一、数据介绍 数据名称&#xff1a;中国地区粮食播种、粮食产量、灾害等数据…

linux 环境运行 jenkins.war包,有可能会出现字体问题,jdk版本:11 jenkins 版本:2.420

jenkins的目录&#xff1a; /usr/jenkins 启动命令 java -Djava.awt.headlesstrue sudo timedatectl set-timezone Asia/Shanghai-Xmx1024m -jar jenkins.war --httpPort8090 任意目录启动&#xff1a; nohup java -Djava.awt.headlesstrue -Xms1024m -Xmx1024m -jar /usr/j…

Spark高级用法-数据源的读取与写入

目录 数据读取 数据写入 总结 数据读取 读文件 read.json read.csv csv文件有两个部分构成 头部数据&#xff0c;也就是字段数据&#xff0c;行数数据 read.orc 读数据库 read.jdbc(jdbc连接地址,table表名,properties{user用户名,password密码,driver驱动信息}) 缺少连…

西门子变频器SINAMICS V20选型

SINAMICS V20共有五种外形尺寸可供选择&#xff0c;输出功率覆盖0.12kW-30kW&#xff1a; V20订货号 单相230V&#xff1a; 三相380V&#xff1a;

Power BI:链接数据库与动态数据展示案例

一、案例背景 在数据驱动的时代&#xff0c;如何高效、直观地展示和分析数据成为了企业决策和个人洞察的关键。Power BI作为一款强大的商业智能工具&#xff0c;凭借其强大的数据连接能力、丰富的可视化选项以及交互性和动态性&#xff0c;成为了众多企业和个人的首选。本文将…