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

原型模式详解及在自动驾驶场景代码示例(c++代码实现)

模式定义

原型模式(Prototype Pattern)是一种创建型设计模式,通过克隆已有对象来创建新对象,避免重复执行昂贵的初始化操作。该模式特别适用于需要高效创建相似对象的场景,是自动驾驶感知系统中处理大量重复数据结构的理想选择。


自动驾驶感知场景分析

在自动驾驶感知系统中,典型的应用场景包括:

  1. 障碍物克隆:快速复制已识别的障碍物模板
  2. 点云分割:高效生成相似的点云聚类实例
  3. 传感器配置:复用基础配置模板创建新传感器实例

本文将重点实现障碍物对象的原型管理模块。


C++实现代码(含详细注释)

#include <iostream>
#include <unordered_map>
#include <memory>
#include <cmath>// ---------------------------- 抽象原型接口 ----------------------------
class ObstaclePrototype {
public:virtual ~ObstaclePrototype() = default;// 克隆接口(关键方法)virtual std::unique_ptr<ObstaclePrototype> clone() const = 0;// 更新状态(示例方法)virtual void updatePosition(float delta_x, float delta_y) = 0;// 显示信息(示例方法)virtual void display() const = 0;
};// ---------------------------- 具体原型实现 ----------------------------
// 车辆障碍物原型
class Vehicle : public ObstaclePrototype {
private:float pos_x;        // X坐标float pos_y;        // Y坐标float length;       // 车长float width;        // 车宽std::string type;   // 车辆类型public:Vehicle(float x, float y, float l, float w, std::string t): pos_x(x), pos_y(y), length(l), width(w), type(std::move(t)) {}// 实现克隆方法(关键实现)std::unique_ptr<ObstaclePrototype> clone() const override {std::cout << "克隆车辆对象 [" << type << "]" << std::endl;return std::make_unique<Vehicle>(*this); // 调用拷贝构造函数}void updatePosition(float delta_x, float delta_y) override {pos_x += delta_x;pos_y += delta_y;}void display() const override {std::cout << "车辆类型: " << type << " 位置(" << pos_x << ", " << pos_y<< ") 尺寸: " << length << "x" << width << std::endl;}// 特有方法:计算占据面积float calculateArea() const {return length * width;}
};// 行人原型
class Pedestrian : public ObstaclePrototype {
private:float pos_x;float pos_y;float speed;int id;public:Pedestrian(float x, float y, float s, int i): pos_x(x), pos_y(y), speed(s), id(i) {}std::unique_ptr<ObstaclePrototype> clone() const override {std::cout << "克隆行人对象 #" << id << std::endl;return std::make_unique<Pedestrian>(*this);}void updatePosition(float delta_x, float delta_y) override {pos_x += delta_x * speed;pos_y += delta_y * speed;}void display() const override {std::cout << "行人 #" << id << " 位置(" << pos_x << ", " << pos_y<< ") 速度: " << speed << "m/s" << std::endl;}// 特有方法:预测运动轨迹void predictTrajectory(float time) const {std::cout << "预测 " << time << "秒后位置: (" << pos_x + speed * time << ", "<< pos_y + speed * time << ")" << std::endl;}
};// ---------------------------- 原型管理器 ----------------------------
class PrototypeManager {
private:std::unordered_map<std::string, std::unique_ptr<ObstaclePrototype>> prototypes;public:// 注册原型void registerPrototype(const std::string& key, std::unique_ptr<ObstaclePrototype> proto) {prototypes[key] = std::move(proto);std::cout << "已注册原型: " << key << std::endl;}// 创建克隆std::unique_ptr<ObstaclePrototype> createClone(const std::string& key) {if (prototypes.find(key) != prototypes.end()) {return prototypes[key]->clone();}std::cerr << "错误: 未找到原型 " << key << std::endl;return nullptr;}// 显示已注册原型void listPrototypes() const {std::cout << "\n=== 已注册原型列表 ===" << std::endl;for (const auto& pair : prototypes) {std::cout << "- " << pair.first << std::endl;}}
};// ---------------------------- 场景演示 ----------------------------
int main() {PrototypeManager manager;// 初始化并注册原型manager.registerPrototype("sedan", std::make_unique<Vehicle>(0, 0, 4.8f, 1.8f, "轿车"));manager.registerPrototype("truck", std::make_unique<Vehicle>(0, 0, 8.5f, 2.5f, "卡车"));manager.registerPrototype("adult", std::make_unique<Pedestrian>(0, 0, 1.2f, 1001));// 显示可用原型manager.listPrototypes();// 动态创建障碍物实例auto obstacle1 = manager.createClone("sedan");auto obstacle2 = manager.createClone("adult");auto obstacle3 = manager.createClone("truck");// 使用克隆对象if (obstacle1) {obstacle1->updatePosition(10.5f, 3.2f);obstacle1->display();// 类型特定操作(需要向下转型)if (auto vehicle = dynamic_cast<Vehicle*>(obstacle1.get())) {std::cout << "车辆面积: " << vehicle->calculateArea() << "m²" << std::endl;}}if (obstacle2) {obstacle2->updatePosition(2.0f, 1.5f);obstacle2->display();if (auto ped = dynamic_cast<Pedestrian*>(obstacle2.get())) {ped->predictTrajectory(5.0f);}}return 0;
}

代码解析

1. 原型接口设计
class ObstaclePrototype {
public:virtual std::unique_ptr<ObstaclePrototype> clone() const = 0;// ...
};
  • 核心克隆方法:强制子类实现对象复制功能
  • 多态支持:统一接口处理各种障碍物类型
2. 具体原型实现
class Vehicle : public ObstaclePrototype {std::unique_ptr<ObstaclePrototype> clone() const override {return std::make_unique<Vehicle>(*this); // 调用拷贝构造函数}// ...
};
  • 深拷贝实现:利用C++的拷贝构造函数确保对象独立性
  • 特有方法保留:各子类可保持专属行为特征
3. 原型管理器
class PrototypeManager {std::unordered_map<std::string, std::unique_ptr<ObstaclePrototype>> prototypes;// ...
};
  • 中央注册表:统一管理所有可用原型
  • 动态扩展:运行时添加/移除原型

运行结果

已注册原型: sedan
已注册原型: truck
已注册原型: adult=== 已注册原型列表 ===
- sedan
- truck
- adult克隆车辆对象 [轿车]
克隆行人对象 #1001
克隆车辆对象 [卡车]
车辆类型: 轿车 位置(10.5, 3.2) 尺寸: 4.8x1.8
车辆面积: 8.64m²
行人 #1001 位置(2.4, 1.8) 速度: 1.2m/s
预测 5秒后位置: (8.4, 7.8)

模式优势分析

在自动驾驶中的价值
  1. 性能优化

    • 避免重复初始化复杂对象(如3D点云数据)
    • 快速复制预处理后的标准障碍物模板
  2. 动态配置

    • 运行时添加新障碍物类型(如特殊车辆)
    • 支持OTA更新障碍物识别参数
  3. 状态保存

    • 克隆历史帧数据用于轨迹预测
    • 创建障碍物快照用于安全校验

扩展改进建议

1. 差异克隆控制
// 扩展克隆接口
enum CloneType { FULL, LIGHTWEIGHT };
virtual std::unique_ptr<ObstaclePrototype> clone(CloneType type) const;
2. 原型版本管理
class VersionedPrototype : public ObstaclePrototype {int version = 1;void updateParameters() { /*...*/ version++; }
};
3. 原型池优化
class PrototypePool {std::vector<std::unique_ptr<ObstaclePrototype>> pool;// 实现对象复用逻辑
};

原型模式总结

核心价值

  • 通过对象克隆替代昂贵的新建操作
  • 保持新对象与原型的一致性
  • 支持动态运行时对象类型扩展

适用场景

  • 需要高效创建大量相似障碍物实例的感知系统
  • 需要保存和恢复传感器数据快照的场景
  • 支持动态加载新障碍物类型的自动驾驶平台

本实现展示了原型模式在自动驾驶感知系统中的典型应用,通过标准化的克隆接口和统一的原型管理,显著提升了系统创建障碍物对象的效率和灵活性。

相关文章:

原型模式详解及在自动驾驶场景代码示例(c++代码实现)

模式定义 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;通过克隆已有对象来创建新对象&#xff0c;避免重复执行昂贵的初始化操作。该模式特别适用于需要高效创建相似对象的场景&#xff0c;是自动驾驶感知系统中处理大量重复数据结构的…...

蓝桥杯常考的找规律题

目录 灵感来源&#xff1a; B站视频链接&#xff1a; 找规律题具有什么样的特点&#xff1a; 报数游戏&#xff08;Java组&#xff09;&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路详解&#xff1a; 代码详解&#xff1a; 阶乘求和&#xff08;Java组…...

MySQL_MCP_Server_pro接入cherry_studio实现大模型操作数据库

大模型直接与数据库交互&#xff0c;实现基本增删改查操作。首先贴下代码地址&#xff1a; https://github.com/wenb1n-dev/mysql_mcp_server_pro 安装环境&#xff1a;win10 1、下载代码 git clone https://github.com/wenb1n-dev/mysql_mcp_server_pro 2、使用conda创建…...

Element UI、Element Plus 里的表单验证的required必填的属性不能动态响应?

一 问题背景 想要实现&#xff1a; 新增/修改对话框中(同一个)&#xff0c;修改时“备注”字段非必填&#xff0c;新增时"备注"字段必填 结果发现直接写不生效-初始化一次性 edit: [{ required: true, message: "请输入备注", trigger: "blur" }…...

Spark-Streaming

WordCount案例 添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"…...

transformer 子层连接结构

子层连接结构 目标 了解什么是子层连接结构掌握子层连接结构的实现过程 什么是子层连接结构? 输入到每个子层以及规范化层的过程中, 使用了残差连接(跳跃连接, 从Add&Norm -> Add&Norm), 因此我们把这一部分结构整体叫做子层连接(代表子层及其链接结构), 在每个…...

linux oracle 19c 静默安装

oracle数据库有个比较很抓瞎的事情&#xff0c;不同的版本搭建的大致流程是一样的&#xff0c;但是在实操细节上会有不同&#xff0c;比如操作的脚本位置和配置项等等&#xff0c;这些会变&#xff0c;所以需要时常积累不同版本的文档 这里有一点要说明&#xff0c;之所以使用…...

C++ 的 输入输出流(I/O Streams)

什么是输入输出流 C 的输入输出操作是通过 流&#xff08;stream&#xff09; 机制实现的。 流——就是数据的流动通道&#xff0c;比如&#xff1a; 输入流&#xff1a;从设备&#xff08;如键盘、文件&#xff09;读取数据 → 程序 输出流&#xff1a;程序将数据写入设备&…...

mybatis-plus开发orm

1、mybatis 使用mybatis-generator自动生成代码 这个也是有系统在使用 2、mybatis-plus开发orm--有的系统在使用 MybatisPlus超详细讲解_mybatis-plus-CSDN博客...

使用Python+OpenCV将多级嵌套文件夹下的视频文件抽帧为JPG图片

使用PythonOpenCV将多级嵌套文件夹下的视频文件抽帧为JPG图片 import os import cv2 import time# 存放视频文件的多层嵌套文件夹路径 videoPath D:\\videos\\ # 保存抽帧的图片的文件夹路径 savePath D:\\images\\if not os.path.exists(savePath):os.mkdir(savePath) vide…...

电子电器架构 --- DFMEA设计失效模式和后果分析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...

C#抽象类和虚方法的作用是什么?

抽象类 (abstract class)&#xff1a; 不能直接实例化&#xff0c;只能被继承。 用来定义一套基础框架和规范&#xff0c;强制子类必须实现某些方法&#xff08;抽象方法&#xff09;。 可用来封装一些共通的逻辑&#xff0c;减少代码重复。 虚方法 (virtual)&#xff1a; …...

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息 输出示例模块示例 输出示例 获取信息&#xff1a;WindowsFormsApp1.Form1.button1_Click(System.Object sender,System.EventArgs e) 引发的异常:“System.IndexOutOfRangeException”(位于 WindowsFormsApp1.ex…...

Apache SeaTunnel:新一代开源、高性能数据集成工具

Apache SeaTunnel 是一款开源、分布式、高性能的数据集成工具&#xff0c;可以通过配置快速搭建数据管道&#xff0c;支持实时海量数据同步。 Apache SeaTunnel 专注于数据集成和数据同步&#xff0c;主要旨在解决数据集成领域的常见问题&#xff1a; 数据源多样性&#xff1a…...

python+selenium+pytest自动化测试chrome driver版本下载

chrome浏览器chromedriver版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/#stable...

3.1 WPF使用MaterialDesign的介绍1

MaterialDesignInXAML Toolkit 是一个流行的开源 C# WPF 控件库,它实现了 Google 的 Material Design 规范,让开发者可以轻松创建现代化的 WPF 应用程序界面 Material Design 是一个流行的设计语言,由 Google 开发,旨在帮助开发者构建美观且一致的 UI 界面。对于使用 C# 的…...

从 0 到 1 打通 AI 工作流:Dify+Zapier 实现工具自动化调用实战

一、引言&#xff1a;当 AI 遇到工具孤岛 在企业数字化转型的浪潮中&#xff0c;AI 工具的应用早已从单一的对话交互进阶到复杂的业务流程自动化。但开发者常常面临这样的困境&#xff1a;本地开发的 MCP 工具&#xff08;如 ERP 数据清洗脚本、CRM 工单系统 API&#xff09;如…...

【算法笔记】如何优雅的进行字符串操作

最近的CCCC天梯赛又出了非常恶心的字符串题~ 在编程竞赛&#xff08;特别是CCCC天梯赛&#xff09;中&#xff0c;字符串操作类题目往往看似简单却暗藏陷阱。本文将以Python、Java、C 三剑客为例&#xff0c;总结高频字符串操作的优雅实现方案&#xff0c;助你快速攻克字符串类…...

docker转移镜像

1、场景 有网络环境向无网络环境转移镜像。无法拉取的镜像&#xff08;外网无法访问&#xff09;下载镜像转移到服务器上。 2、docker转移 2.1 镜像服务器 保存镜像 列出项目使用的所有镜像 docker images 保存所有镜像为 tar 文件 保存docker镜像 docker save -o my_…...

【Rust 精进之路之第12篇-生命周期·入门】为何需要与显式标注 (`‘a`):让编译器读懂引用的“有效期”

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:悬垂引用的“幽灵”与编译器的“侦探” 在前面的章节中,我们深入学习了 Rust 的所有权系统,以及如何通过引用 (& 和 &mut) 进行借用,从而在不转移所有权的情况下安…...

Vue.js 之 `v-for` 命令详解

Vue.js 之 v-for 命令详解 在 Vue.js 中&#xff0c;v-for 是一个非常强大的指令&#xff0c;用于遍历数组或对象中的数据&#xff0c;并渲染相应的 DOM 元素。无论是在列表展示、表单生成还是动态组件加载中&#xff0c;v-for 都发挥着重要作用。本文将详细介绍 v-for 的用法…...

Spring Boot中`logging.config`配置项的详解及使用说明

以下是Spring Boot中logging.config配置项的详解及使用说明&#xff1a; 1. logging.config 作用 功能&#xff1a;指定自定义日志配置文件的路径&#xff0c;覆盖Spring Boot默认的日志配置。适用场景&#xff1a;当需要深度定制日志行为&#xff08;如输出格式、文件路径、…...

相机模型--CMOS和CCD的区别

1--CMOS和CCD的工作原理 CCD&#xff08;Charge Coupled Device&#xff0c;电荷耦合器件&#xff09;&#xff1a; 1. 图像通过光电效应在感光单元中转化为电荷&#xff1b; 2. 每个像素上的电荷被依次“耦合”并传输到芯片的角落&#xff0c;通过一个或几个模拟输出放大器输…...

el-date-picker时间范围 赋值报错问题

问题&#xff1a; 点击时间范围组件右边清除图标&#xff0c;点击近6小时会把设置好的时间赋值给时间范围组件 但是出现报错 原因&#xff1a; 尝试对null值进行属性设置操作&#xff1a;修改一个数组的元素&#xff0c;但此时这个数组是null&#xff0c;而不是预期的数组类型…...

为啥低速MCU单板辐射测试会有200M-1Ghz的辐射信号

低速MCU&#xff08;如8位或16位单片机&#xff09;单板在辐射测试中出现 200MHz~1GHz的高频辐射信号&#xff0c;看似不合理&#xff0c;但实际上是由多种因素共同导致的。以下是详细原因分析及解决方案&#xff1a; 1.根本原因分析: (1) 时钟谐波与开关噪声 低速MCU的时钟谐…...

【音视频】FFmpeg解封装

解封装 复用器&#xff0c;比如MP4/FLV 解复用器&#xff0c;MP4/FLV 封装格式相关函数 avformat_alloc_context(); 负责申请一个AVFormatContext结构的内存,并进行简单初始化avformat_free_context(); 释放该结构里的所有东西以及该结构本身avformat_close_input();关闭解复…...

使用VHDL语言实现TXT文件的读写操作

使用FPGA进行图像处理时&#xff0c;通常需要将TXT文件中的图像数据读出到TestBench中&#xff0c;并将仿真的结果写入到TXT文件中&#xff0c;用于确认图像处理的结果是否正确。 VHDL中TXT文件的读写操作如下所示&#xff0c; --------------------------------------------…...

OpenLDAP 管理 ELK 用户

文章目录 一、新建 ELK 相关用户组二、配置 Elasticsearch2.1 修改 elasticsearch.yml 配置2.2 使用 API 接口建立角色和用户映射 三、Kibana 验证用户登录 一、新建 ELK 相关用户组 由于后续要将 LDAP 的用户与 ELK 的角色进行映射&#xff0c;所以需先创建几个以 ELK 的角色…...

第十七届“华中杯”大学生数学建模挑战赛题目A题 晶硅片产销策略优化 完整成品 代码 模型 思路 分享

近年来&#xff0c;高纯度晶硅片需求的增长引发了更激烈的市场竞争。晶硅片企业需要在成本控制、利润优化和供需管理之间取得平衡&#xff0c;以提高经营效率和市场竞争力。晶硅片的生产是一个高能耗、高成本的过程&#xff0c;企业效益会受到原材料价格波动、市场需求变化以及…...

iOS 中的虚拟内存 (理解为什么需要虚拟内存)

什么叫“虚拟地址空间”&#xff1f; 一句话&#xff1a;它是 CPU 看得见、App 以为自己独享&#xff0c;但实际上会被内核和硬件&#xff08;MMU&#xff09;动态翻译到真实 物理内存 的一整块“虚拟地图”。 1. 背景&#xff1a;为什么要“虚拟”&#xff1f; 需求虚拟地址空…...