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

【设计模式之美】【建造型】工厂模式:通过面向接口编程思路,串起业务流程

文章目录

  • 一. 简单工厂(Simple Factory)
    • 第一种简单工厂:面向接口编程与工厂类:划分功能职责
    • 第二种:单例+简单工厂:节省内存和对象创建的时间
  • 二. 工厂方法(Factory Method):进一步抽象:通过面向接口的思路创建对象
  • 三. 什么时候使用工厂方法
  • 四. 抽象工厂

一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。

什么时候该用工厂模式?相对于直接 new 来创建对象,用工厂模式来创建究竟有什么好处呢?这是本文将要讨论的事情。

 

一. 简单工厂(Simple Factory)

第一种简单工厂:面向接口编程与工厂类:划分功能职责

如下代码流程描述了:根据不同的文件后缀(面向接口编程)创建不同的对象,然后执行相同方法的不同逻辑。

public class RuleConfigSource {public RuleConfig load(String ruleConfigFilePath) {//1. 获取文件后缀String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);//这个是函数式接口,有一个抽象方法parse。//2. 根据不同的文件后缀,创建不同的parse对象(面向接口编程)IRuleConfigParser parser = null;if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {parser = new JsonRuleConfigParser();} else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {parser = new XmlRuleConfigParser();} else if ("yaml".equalsIgnoreCase(ruleConfigFileExtension)) {parser = new YamlRuleConfigParser();} else if ("properties".equalsIgnoreCase(ruleConfigFileExtension)) {parser = new PropertiesRuleConfigParser();} else {throw new InvalidRuleConfigException("Rule config file format is not supported: " + ruleConfigFilePath);}//3. 根据具体实现解析文本String configText = "";//从ruleConfigFilePath文件中读取配置文本到configText中RuleConfig ruleConfig = parser.parse(configText);return ruleConfig;}private String getFileExtension(String filePath) {//...解析文件名获取扩展名,比如rule.json,返回jsonreturn "json";}
}

 

为了增加代码的可读性:将功能独立的代码封装成函数:将创建对象的逻辑抽取出来

  public RuleConfig load(String ruleConfigFilePath) {String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);//1. 创建对象IRuleConfigParser parser = createParser(ruleConfigFileExtension);//check parser=?nullString configText = "";//从ruleConfigFilePath文件中读取配置文本到configText中//2. 执行指定对象的parse方法(面向接口编程)RuleConfig ruleConfig = parser.parse(configText);return ruleConfig;}private String getFileExtension(String filePath) {//...解析文件名获取扩展名,比如rule.json,返回jsonreturn "json";}private IRuleConfigParser createParser(String configFormat) {IRuleConfigParser parser = null;if ("json".equalsIgnoreCase(configFormat)) {parser = new JsonRuleConfigParser();} else if ("xml".equalsIgnoreCase(configFormat)) {parser = new XmlRuleConfigParser();} else if ("yaml".equalsIgnoreCase(configFormat)) {parser = new YamlRuleConfigParser();} else if ("properties".equalsIgnoreCase(configFormat)) {parser = new PropertiesRuleConfigParser();}return parser;}
}

 

类责任单一:对象创建的方法放到独立一个类中,具体地,
将 createParser() 函数剥离到一个独立的类中,让这个类只负责对象的创建。

...public class RuleConfigParserFactory {public static IRuleConfigParser createParser(String configFormat) {IRuleConfigParser parser = null;if ("json".equalsIgnoreCase(configFormat)) {parser = new JsonRuleConfigParser();} else if ("xml".equalsIgnoreCase(configFormat)) {parser = new XmlRuleConfigParser();} else if ("yaml".equalsIgnoreCase(configFormat)) {parser = new YamlRuleConfigParser();} else if ("properties".equalsIgnoreCase(configFormat)) {parser = new PropertiesRuleConfigParser();}return parser;}
}

类名与方法名:

  • 大部分工厂类都是以“Factory”这个单词结尾的,但也不是必须的,比如 Java 中的 DateFormat、Calender。
  • 工厂类中创建对象的方法一般都是 create 开头,比如代码中的 createParser(),但有的也命名为 getInstance()、createInstance()、newInstance(),有的甚至命名为 valueOf()(比如 Java String 类的 valueOf() 函数)等等,这个我们根据具体的场景和习惯来命名就好。

 

面向接口编程


面向接口编程(Interface-Oriented Programming)其核心思想是依赖于接口(或抽象类)来编写程序,而不是依赖于具体的实现类。具体地,通过接口来串联起业务代码的逻辑,而不是具体的实现类。

 

面向接口有如下好处:

  • 松耦合:各个模块之间的依赖关系更松散。这使得系统中的组件可以更独立地开发、测试和部署
  • 可扩展性:新的功能可以通过实现现有接口来扩展系统,而不会影响到已有的代码。
  • 增强代码复用:通过面向接口编程,可以提高代码的可重用性。不同的实现类可以实现相同的接口,使得同一份代码可以适应不同的实际需求。
  • 测试和调试:面向接口编程使得单元测试更加容易,可以使用模拟对象(mock objects)来模拟接口的行为,从而进行更有效的单元测试和调试。

 

第二种:单例+简单工厂:节省内存和对象创建的时间

为了节省内存和对象创建的时间,我们可以将 parser 事先创建好缓存起来。当调用 createParser() 函数的时候,我们从缓存中取出 parser 对象直接使用。

public class RuleConfigParserFactory {private static final Map<String, RuleConfigParser> cachedParsers = new HashMap<>();static {cachedParsers.put("json", new JsonRuleConfigParser());cachedParsers.put("xml", new XmlRuleConfigParser());cachedParsers.put("yaml", new YamlRuleConfigParser());cachedParsers.put("properties", new PropertiesRuleConfigParser());}public static IRuleConfigParser createParser(String configFormat) {if (configFormat == null || configFormat.isEmpty()) {return null;//返回null还是IllegalArgumentException全凭你自己说了算}//也去掉了if elseIRuleConfigParser parser = cachedParsers.get(configFormat.toLowerCase());return parser;}
}

对于上面两种简单工厂模式的实现方法,如果我们要添加新的 parser,那势必要改动到 RuleConfigParserFactory 的代码,那这是不是违反开闭原则呢?实际上,如果不是需要频繁地添加新的 parser,只是偶尔修改一下 RuleConfigParserFactory 代码,稍微不符合开闭原则,也是完全可以接受的。

 

总结一下,尽管简单工厂模式的代码实现中,有多处 if 分支判断逻辑,违背开闭原则,但权衡扩展性和可读性,这样的代码实现在大多数情况下(比如,不需要频繁地添加 parser,也没有太多的 parser)是没有问题的。

 

二. 工厂方法(Factory Method):进一步抽象:通过面向接口的思路创建对象

如果我们非得要将 if 分支逻辑去掉,那该怎么办呢?比较经典处理方法就是利用多态。按照多态的实现思路,对上面的代码进行重构。

如下我们新增一个创建对象的工厂,这样当我们新增一种 parser 的时候,只需要新增一个实现了 IRuleConfigParserFactory 接口的 Factory 类即可。所以,工厂方法模式比起简单工厂模式更加符合开闭原则

public interface IRuleConfigParserFactory {IRuleConfigParser createParser();
}public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory {@Overridepublic IRuleConfigParser createParser() {return new JsonRuleConfigParser();}
}XmlRuleConfigParserFactory
YamlRuleConfigParserFactory
...-------------public class RuleConfigSource {public RuleConfig load(String ruleConfigFilePath) {String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);IRuleConfigParserFactory parserFactory = null;if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {parserFactory = new JsonRuleConfigParserFactory();} else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {parserFactory = new XmlRuleConfigParserFactory();} else if ("yaml".equalsIgnoreCase(ruleConfigFileExtension)) {parserFactory = new YamlRuleConfigParserFactory();} else if ("properties".equalsIgnoreCase(ruleConfigFileExtension)) {parserFactory = new PropertiesRuleConfigParserFactory();} else {throw new InvalidRuleConfigException("Rule config file format is not supported: " + ruleConfigFilePath);}// 这里是工厂方法的关键思路点:通过面向接口的思路来创建对象IRuleConfigParser parser = parserFactory.createParser();String configText = "";RuleConfig ruleConfig = parser.parse(configText);return ruleConfig;}}

但注意代码的复杂度此时增加了

工厂类对象的创建逻辑又耦合进了 load() 函数中,跟我们最初的代码版本非常相似,引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了。

 

我们为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。


public class RuleConfigSource {public RuleConfig load(String ruleConfigFilePath) {String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);IRuleConfigParserFactory parserFactory = RuleConfigParserFactoryMap.getParserFactory(ruleConfigFileExtension);if (parserFactory == null) {throw new InvalidRuleConfigException("Rule config file format is not supported: " + ruleConfigFilePath);}IRuleConfigParser parser = parserFactory.createParser();String configText = "";//从ruleConfigFilePath文件中读取配置文本到configText中RuleConfig ruleConfig = parser.parse(configText);return ruleConfig;}private String getFileExtension(String filePath) {//...解析文件名获取扩展名,比如rule.json,返回jsonreturn "json";}
}//因为工厂类只包含方法,不包含成员变量,完全可以复用,
//不需要每次都创建新的工厂类对象,所以,简单工厂模式的第二种实现思路更加合适。
public class RuleConfigParserFactoryMap { //工厂的工厂private static final Map<String, IRuleConfigParserFactory> cachedFactories = new HashMap<>();static {cachedFactories.put("json", new JsonRuleConfigParserFactory());cachedFactories.put("xml", new XmlRuleConfigParserFactory());cachedFactories.put("yaml", new YamlRuleConfigParserFactory());cachedFactories.put("properties", new PropertiesRuleConfigParserFactory());}public static IRuleConfigParserFactory getParserFactory(String type) {if (type == null || type.isEmpty()) {return null;}IRuleConfigParserFactory parserFactory = cachedFactories.get(type.toLowerCase());return parserFactory;}
}

当我们需要添加新的规则配置解析器的时候,我们只需要创建新的 parser 类和 parser factory 类,并且在 RuleConfigParserFactoryMap 类中,将新的 parser factory 对象添加到 cachedFactories 中即可。代码的改动非常少,基本上符合开闭原则。

 

三. 什么时候使用工厂方法

实际上,对于规则配置文件解析这个应用场景来说,工厂模式需要额外创建诸多 Factory 类,也会增加代码的复杂性,而且,每个 Factory 类只是做简单的 new 操作,功能非常单薄(只有一行代码),也没必要设计成独立的类,所以,在这个应用场景下,简单工厂模式简单好用,比工厂方法模式更加合适。

 

那什么时候该用工厂方法模式,而非简单工厂模式呢?

  • 如果代码块本身并不复杂,就几行代码而已,我们完全没必要将它拆分成单独的函数或者类。
  • 当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。比如:不同jdbc数据源的管理、flink connector的管理。

 

四. 抽象工厂

抽象工厂模式的应用场景比较特殊,没有前两种常用。

在简单工厂和工厂方法中,类只有一种分类方式。当有多个类的分类时,我们可以让一个工厂负责创建多个不同类型的对象,而不是只创建一种 parser 对象。如下:

public interface IConfigParserFactory {IRuleConfigParser createRuleParser();ISystemConfigParser createSystemParser();//此处可以扩展新的parser类型,比如IBizConfigParser
}public class JsonConfigParserFactory implements IConfigParserFactory {@Overridepublic IRuleConfigParser createRuleParser() {return new JsonRuleConfigParser();}@Overridepublic ISystemConfigParser createSystemParser() {return new JsonSystemConfigParser();}
}... 
XmlConfigParserFactory 
YamlConfigParserFactory
PropertiesConfigParserFactory

参考:
王争:《设计模式之美》

相关文章:

【设计模式之美】【建造型】工厂模式:通过面向接口编程思路,串起业务流程

文章目录 一. 简单工厂&#xff08;Simple Factory&#xff09;第一种简单工厂&#xff1a;面向接口编程与工厂类&#xff1a;划分功能职责第二种&#xff1a;单例简单工厂&#xff1a;节省内存和对象创建的时间 二. 工厂方法&#xff08;Factory Method&#xff09;&#xff1…...

AI算法19-偏最小二乘法回归算法Partial Least Squares Regression | PLS

偏最小二乘法回归算法简介 算法概述 偏最小二乘法模型可分为偏最小二乘回归模型和偏最小二乘路径模型。其中偏最小二乘回归模型是一种新型的多元统计方法&#xff0c;它集中了主成分分析、典型相关分析和线性回归的特点&#xff0c;特别在解决回归中的共线性问题具有无可比拟…...

live555关于RTSP协议交互流程

RTP在和h264 RTP在和h265 RTP载荷AAC live555关于RTSP协议交互流程 live555的核心数据结构值之闭环双向链表 live555 rtsp服务器实战之createNewStreamSource 概要 rtsp在交互的过程中用到很多协议:tcp,udp,rtp,rtcp,sdp等协议&#xff1b;该篇文章主要分析在live555中这些…...

Centos7 安装私有 Gitlab

在 CentOS 7上&#xff0c;下面的命令也会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您打算仅从本地网络访问极狐GitLab&#xff0c;则可以跳过它。 sudo yum install -y curl policycoreutils-python openssh-server perl sudo systemct…...

浅谈数学模型在UGC/AIGC游戏数值配置调参中的应用(AI智能体)

浅谈数学模型在UGC/AIGC游戏数值配置调参中的应用 ygluu 卢益贵 关键词&#xff1a;UGC、AIGC、AI智能体、大模型、数学模型、游戏数值调参、游戏策划 一、前言 在策划大大群提出《游戏工厂&#xff1a;AI&#xff08;AIGC/ChatGPT&#xff09;与流程式游戏开发》讨论之后就…...

第T5周:使用TensorFlow实现运动鞋品牌识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文章目录 一、前期工作1.设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据 二、数据预处理1、加载数据2、数据可视化3、再…...

网络编程学习之tcp

按下*&#xff08;星号&#xff09;可以搜索当前光标下的单词。 Tcp编程的过程 打开网络设备 Bind&#xff1a;给服务地址把ip号和端口号连接进去 Tcp是有状态的 Listen是进入监听状态&#xff0c;看有没有客户端来连接服务器 Tcp比udp消耗过多资源 Upd类似于半双工&#…...

前端XMLHttpRequest、Fetch API、Axios实现文件上传、下载方法及后端Spring文件服务器处理方法

前言 本文总结Web应用开发中文件上传、下载的方法&#xff0c;即从前端表单输入文件并封装表单数据&#xff0c;然后请求后端服务器的处理过程&#xff1b;从基础的JavaScript中XmlHttpRequest对象、Fetch API实现上传、下载进行说明&#xff0c;并给出了前端常用的axios库的请…...

STM32智能交通监测系统教程

目录 引言环境准备智能交通监测系统基础代码实现&#xff1a;实现智能交通监测系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;交通监测与管理问题解决方案与优化收尾与总结 1. 引言 智能交通监测系统通…...

【利用Selenium+autoIt实现文件上传】

利用Selenium+autoIt实现文件上传 利用Selenium+autoIT实现文件上传autoIt脚本制作转换成exe文件java代码运行部分利用Selenium+autoIT实现文件上传 当你看到这篇文章时,证明你遇到了和我一样的难题。正常情况下我们利用selenium完全可以实现表单的提交和文件上传等操作。但当…...

python join

1、join函数 *.join(seq) 以*作为分隔符&#xff0c;将seq所有的元素合并为一个新的字符串 seq ABDWDPO new_seq list(.joint(seq)) # ABDWDPO #[A, B, D, W, D, P, O]...

cython加速python代码

python这个语言在使用的层面上看几乎没有缺点&#xff0c;简单易学&#xff0c;语法简单&#xff0c;唯一的弱点就是慢&#xff0c; 当然了万能的python社区是给了解决方法的&#xff0c;那就是cython 使用Cython可以显著提升Python代码的执行效率&#xff0c;特别是在涉及到数…...

React@16.x(60)Redux@4.x(9)- 实现 applyMiddleware

目录 1&#xff0c;applyMiddleware 原理2&#xff0c;实现2.1&#xff0c;applyMiddleware2.1.1&#xff0c;compose 方法2.1.2&#xff0c;applyMiddleware 2.2&#xff0c;修改 createStore 接上篇文章&#xff1a;Redux中间件介绍。 1&#xff0c;applyMiddleware 原理 R…...

level 6 day1 Linux网络编程之网络基础

v1 网络的历史和分层 TCP 是可靠传输&#xff0c;IP协议是不可靠传输 网络的体系结构 网络分层的思想&#xff1a; OSI体系结构 两层交换机是指数据链路层的交换 三层交换是指网络层这边的交换 四层模型 蓝色的字 是由手机发给PC机&#xff0c;由传输层来决定应该交给哪一…...

PostgreSQL UPDATE 命令

PostgreSQL UPDATE 命令 PostgreSQL 是一种功能强大的开源对象关系型数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;它使用并扩展了SQL语言。在处理数据库时&#xff0c;我们经常需要更新现有的记录。在PostgreSQL中&#xff0c;UPDATE命令用于修改表中的现有记录…...

什么? CSS 将支持 if() 函数了?

CSS Working Group 简称 CSSWG, 在近期的会议中决定将 if() 添加到 CSS Values Module Level 5 中。 详情可见&#xff1a;css-meeting-bot 、[css-values] if() function 当我看到这个消息的时候&#xff0c;心中直呼这很逆天了&#xff0c;我们知道像 less 这些 css 这些预…...

function calling实现调用理杏仁api获取数据

LLM是不存在真正逻辑的且并不是知晓万事万物的&#xff08;至少目前是这样&#xff09;在很多更垂直的环境下LLM并不能很好的赋能。 function calling的实现使LLM可以对接真正的世界以及真正有逻辑的系统&#xff0c;这将很大程度上改变LLM的可用范围&#xff08;当然安全问题依…...

Excel中用VBA实现Outlook发送当前工作簿

Excel中用VBA实现Outlook发送当前工作簿&#xff0c;首先按AltF11打开VBA编辑器&#xff0c;插入模块&#xff0c;并在工具-引用中勾选 Microseft Outlook .0 Object Library(其中为你Microseft Outlook的版本号。 Sub 发送邮件() 保存当前excel ThisWorkbook.Save让excel连接…...

从 ArcMap 迁移到 ArcGIS Pro

许多 ArcMap 用户正在因 ArcGIS Pro 所具有的现代 GIS 桌面工作流优势而向其迁移。 ArcGIS Pro 与其余 ArcGIS 平台紧密集成&#xff0c;使您可以更有效地共享和使用内容。 它还将 2D 和 3D 组合到一个应用程序中&#xff0c;使您可以在同一工程中使用多个地图和多个布局。 Arc…...

WSL2 的安装与运行 Linux 系统

前言 适用于 Linux 的 Windows 子系统 (WSL) 是 Windows 的一项功能&#xff0c;允许开发人员在 Windows 系统上直接安装并使用 Linux 发行版。不用进行任何修改&#xff0c;也无需承担传统虚拟机或双启动设置的开销。 可以将 WSL 看作也是一个虚拟机&#xff0c;但是它更为便…...

SmallThinker-3B-Preview赋能Java后端:智能客服系统数据库设计

SmallThinker-3B-Preview赋能Java后端&#xff1a;智能客服系统数据库设计 最近在做一个Java后端的智能客服项目&#xff0c;核心是要接入一个轻量级的AI模型——SmallThinker-3B-Preview。模型选好了&#xff0c;代码逻辑也搭得差不多了&#xff0c;但一到数据库设计这块&…...

Phi-4-mini-reasoning效果展示:同参数量级中推理准确率超Llama3-8B实测对比

Phi-4-mini-reasoning效果展示&#xff1a;同参数量级中推理准确率超Llama3-8B实测对比 1. 开篇亮点&#xff1a;小模型的大智慧 Phi-4-mini-reasoning这款仅有3.8B参数的轻量级开源模型&#xff0c;正在重新定义我们对小模型能力的认知。作为专为数学推理、逻辑推导和多步解…...

终极指南:如何在NixOS上完美打包与使用SilentSDDM主题

终极指南&#xff1a;如何在NixOS上完美打包与使用SilentSDDM主题 【免费下载链接】SilentSDDM A very customizable SDDM theme that actually looks good. 项目地址: https://gitcode.com/gh_mirrors/si/SilentSDDM SilentSDDM是一款高度可定制且视觉精美的SDDM登录主…...

深入解析RevokeMsgPatcher:Windows平台防撤回补丁的技术实现与架构设计

深入解析RevokeMsgPatcher&#xff1a;Windows平台防撤回补丁的技术实现与架构设计 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁&#xff08;我已经看到了&#xff0c;撤回也没用了&#xff09; 项目地址: ht…...

Seqlist 顺序表 的实现c语言

本小结重点&#xff1a; 你将学到 函数基础 传值传地址的区别结构体指针 简单循环控制 理解物理结构与存储结构的区别多文件分布 简单来说就是对动态数组进行函数封装&#xff0c;简化了很多功能所以很多就是对数组的利用&#xff0c;但更多是对结构体数组&#xff0c;所…...

RTX3070 + CUDA 11.0 实战:手把手教你从零搭建 PointNet.pytorch 环境(附常见报错解决)

RTX3070 CUDA 11.0 实战&#xff1a;手把手教你从零搭建 PointNet.pytorch 环境&#xff08;附常见报错解决&#xff09; 当你手握一块RTX3070显卡&#xff0c;想要复现PointNet这一经典点云处理网络时&#xff0c;是否曾被环境配置的各种坑绊住脚步&#xff1f;本文将带你避开…...

创维E900V22D_S905L3S(B)芯片-安卓9.0-免拆线刷固件包及短接神器使用指南

1. 创维E900V22D刷机前的准备工作 拿到创维E900V22D机顶盒的第一件事&#xff0c;就是确认它的硬件配置。这个型号采用的是晶晨S905L3S(B)芯片方案&#xff0c;运行的是安卓9.0系统。我遇到过不少朋友因为没看清芯片型号就开刷&#xff0c;结果把盒子刷成砖的案例。所以一定要先…...

AT命令驱动的跨平台嵌入式Web服务器框架

1. 项目概述ESP8266_AT_WebServer 是一个面向嵌入式硬件工程师的轻量级、跨平台 Web 服务框架&#xff0c;其核心设计哲学是“硬件无关性”与“协议抽象化”。它并非直接运行于 ESP8266/ESP32 芯片之上&#xff0c;而是将这些 Wi-Fi 模块降级为一个标准的 AT 命令外设&#xff…...

AI辅助快速模拟:在快马平台用C语言生成ahflt.sys驱动行为原型

今天想和大家分享一个有趣的实验&#xff1a;如何在InsCode(快马)平台上快速模拟Windows驱动行为。最近在研究ahflt.sys这个系统文件时&#xff0c;发现直接操作真实驱动既复杂又有风险&#xff0c;于是尝试用C语言写了个控制台程序来模拟它的基础行为。 项目背景与需求分析 ah…...

为什么自动驾驶地铁离不开形式化方法?从法国B方法到上海15号线的实战解析

数学如何为自动驾驶地铁筑起安全屏障&#xff1a;从B方法到工业级验证的深度实践 当一列无人驾驶的地铁以80公里时速穿越隧道时&#xff0c;系统每毫秒需要处理200传感器信号、执行30余项控制决策。巴黎地铁14号线自1998年开通以来保持零重大事故记录&#xff0c;上海15号线全自…...