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

[C++] --- 常用设计模式

策略模式
迭代器模式
适配器模式
工厂模式
超级工厂模式
享元模式
代理模式

1 策略模式

策略模式(Strategy Pattern)是一种行为型设计模式,其核心思想是将算法家族封装起来,让它们之间可以互相替换,从而使算法的变化独立于使用算法的客户端。这种模式特别适合处理 “同一问题存在多种解决方案,且需要动态选择其中一种” 的场景。

策略模式包含三个关键角色:

  • 环境类(Context):持有策略对象的引用,负责调用具体策略
  • 抽象策略接口(Strategy):定义所有具体策略的公共接口
  • 具体策略类(ConcreteStrategy):实现抽象策略接口,包含具体算法

适用场景

  • 一个问题有多种解决方案,需要动态选择其中一种
  • 算法需要被复用或替换
  • 避免使用多重条件判断语句

代码示例:

#include <iostream>
#include <vector>
#include <memory>
#include <string>// 路径点结构
struct PathPoint {double x;  // x坐标double y;  // y坐标double theta;  // 航向角
};// 1. 抽象策略接口:路径规划算法
class PathPlanningStrategy {
public:virtual ~PathPlanningStrategy() = default;// 纯虚函数:规划路径virtual std::vector<PathPoint> plan(const PathPoint& start, const PathPoint& goal,const std::vector<PathPoint>& obstacles) = 0;// 获取算法名称virtual std::string getName() const = 0;
};// 2. 具体策略类:A*算法
class AStarStrategy : public PathPlanningStrategy {
public:std::vector<PathPoint> plan(const PathPoint& start, const PathPoint& goal,const std::vector<PathPoint>& obstacles) override {std::cout << "使用A*算法规划路径..." << std::endl;// 实际实现中会根据起点、终点和障碍物计算路径return {start, {5.0, 3.0, 0.5}, {10.0, 5.0, 0.8}, goal};}std::string getName() const override {return "A*算法";}
};// 3. 具体策略类:RRT算法
class RRTStrategy : public PathPlanningStrategy {
public:std::vector<PathPoint> plan(const PathPoint& start, const PathPoint& goal,const std::vector<PathPoint>& obstacles) override {std::cout << "使用RRT算法规划路径..." << std::endl;// RRT算法的具体实现return {start, {2.0, 4.0, 0.3}, {8.0, 6.0, 0.6}, goal};}std::string getName() const override {return "RRT算法";}
};// 4. 具体策略类:Dijkstra算法
class DijkstraStrategy : public PathPlanningStrategy {
public:std::vector<PathPoint> plan(const PathPoint& start, const PathPoint& goal,const std::vector<PathPoint>& obstacles) override {std::cout << "使用Dijkstra算法规划路径..." << std::endl;// Dijkstra算法的具体实现return {start, {3.0, 2.0, 0.4}, {9.0, 4.0, 0.7}, goal};}std::string getName() const override {return "Dijkstra算法";}
};// 5. 环境类:路径规划器
class PathPlanner {
private:// 持有策略对象std::unique_ptr<PathPlanningStrategy> strategy_;public:// 构造函数,默认使用A*算法PathPlanner() : strategy_(std::make_unique<AStarStrategy>()) {}// 允许动态设置策略void setStrategy(std::unique_ptr<PathPlanningStrategy> strategy) {if (strategy) {strategy_ = std::move(strategy);}}// 执行路径规划std::vector<PathPoint> planPath(const PathPoint& start, const PathPoint& goal,const std::vector<PathPoint>& obstacles) {if (!strategy_) {throw std::runtime_error("未设置路径规划策略");}std::cout << "当前使用的路径规划算法: " << strategy_->getName() << std::endl;return strategy_->plan(start, goal, obstacles);}
};// 客户端代码
int main() {// 创建路径规划器PathPlanner planner;// 定义起点、终点和障碍物PathPoint start = {0.0, 0.0, 0.0};PathPoint goal = {10.0, 10.0, 1.0};std::vector<PathPoint> obstacles = {{3.0, 3.0, 0.0}, {7.0, 7.0, 0.0}};// 使用默认策略(A*)规划路径auto path1 = planner.planPath(start, goal, obstacles);// 切换策略为RRTplanner.setStrategy(std::make_unique<RRTStrategy>());auto path2 = planner.planPath(start, goal, obstacles);// 切换策略为Dijkstraplanner.setStrategy(std::make_unique<DijkstraStrategy>());auto path3 = planner.planPath(start, goal, obstacles);return 0;
}

代码解析, 在这个智能驾驶路径规划的示例中:
抽象策略接口 PathPlanningStrategy 定义了所有路径规划算法的公共接口,包含规划路径的纯虚函数 plan 和获取算法名称的 getName。
具体策略类 AStarStrategy、RRTStrategy 和 DijkstraStrategy 分别实现了三种不同的路径规划算法,每种算法都有自己的实现逻辑。
环境类 PathPlanner 持有一个策略对象,提供了 setStrategy 方法允许动态切换算法,并通过 planPath 方法调用当前策略的规划功能。
客户端代码 可以根据需要(如不同路况、不同精度要求)动态切换路径规划算法,而无需修改 PathPlanner 或算法本身的代码。

2 适配器模式

适配器模式(Adapter Pattern)是一种结构型设计模式,其核心是将一个类的接口转换成客户端期望的另一种接口,使原本因接口不兼容而无法协作的类能够一起工作。在智能驾驶开发中,由于传感器、算法、硬件的多样性,适配器模式被广泛用于解决接口适配问题。

核心解决的问题

  • 接口兼容性:当新组件(如第三方算法、新型传感器)的接口与现有系统不一致时,无需修改原有代码即可使其兼容。
  • 复用性扩展:复用已有功能组件(如开源算法),通过适配使其融入现有架构,避免重复开发。
  • 系统稳定性:隔离外部组件的接口变化,原有系统代码无需修改,降低维护成本。

核心角色

  • 目标接口(Target):客户端期望的统一接口,定义了系统需要的功能规范。
  • 适配者(Adaptee):需要被适配的现有类或接口(如第三方算法、硬件驱动),其接口与目标接口不兼容。
  • 适配器(Adapter):实现目标接口,内部持有适配者的引用,将目标接口的调用转换为对适配者的调用。

两种实现方式

  • 类适配器:通过多重继承(继承目标接口和适配者)实现适配(C++ 支持,但因多重继承复杂性较少使用)。
  • 对象适配器:通过组合(持有适配者对象)实现适配,更灵活,是主流实现方式。

代码示例:

#include <iostream>
#include <vector>
#include <string>
#include <memory>// ------------------------------
// 1. 目标接口(Target):系统期望的统一检测接口
// ------------------------------
struct DetectionResult {std::string class_name;  // 目标类别(如"car"、"pedestrian")float x;                 // 检测框x坐标float y;                 // 检测框y坐标float width;             // 检测框宽度float height;            // 检测框高度float confidence;        // 置信度
};// 目标接口:统一的目标检测器接口
class TargetDetector {
public:virtual ~TargetDetector() = default;// 初始化检测器(返回是否成功)virtual bool init(const std::string& model_path) = 0;// 检测接口(输入图像数据,输出检测结果)virtual std::vector<DetectionResult> detect(const unsigned char* image_data, int width, int height) = 0;// 获取算法名称virtual std::string getName() const = 0;
};// ------------------------------
// 2. 适配者(Adaptee):需要被适配的第三方算法
// ------------------------------// 适配者1:YOLO算法(接口与目标接口不兼容)
class YoloAlgorithm {
public:// YOLO的初始化接口(参数不同)bool loadModel(const std::string& model_path, int gpu_id) {std::cout << "YoloAlgorithm: 加载模型 " << model_path << " (GPU ID: " << gpu_id << ")\n";return true;  // 模拟成功加载}// YOLO的检测接口(输入输出格式不同)struct YoloResult {int class_id;    // 类别ID(而非名称)float bbox[4];   // [x1, y1, x2, y2](与目标接口的宽高格式不同)float score;     // 分数(对应置信度)};std::vector<YoloResult> runDetection(const unsigned char* img, int w, int h, float threshold) {  // 多了阈值参数// 模拟检测结果return {{0, {100, 200, 300, 400}, 0.92},  // 假设class_id=0对应"car"{1, {50, 150, 150, 350}, 0.88}   // 假设class_id=1对应"pedestrian"};}
};// 适配者2:Faster R-CNN算法(接口不同)
class FasterRCNNAlgorithm {
public:// Faster R-CNN的初始化接口(无GPU参数)void initialize(const std::string& model_file, const std::string& config_file) {std::cout << "FasterRCNNAlgorithm: 初始化模型 " << model_file << " (配置: " << config_file << ")\n";}// Faster R-CNN的检测接口(返回格式不同)std::vector<std::tuple<std::string, float, float, float, float, float>> detectObjects(const unsigned char* image, int width, int height) {// 模拟检测结果(格式:(类别名, x, y, w, h, 置信度))return {{"car", 120, 220, 180, 190, 0.90},{"cyclist", 80, 180, 60, 120, 0.85}};}
};// ------------------------------
// 3. 适配器(Adapter):将适配者转换为目标接口
// ------------------------------// 适配器1:YOLO算法适配器
class YoloAdapter : public TargetDetector {
private:YoloAlgorithm yolo_;  // 持有适配者对象int gpu_id_;          // YOLO特有的参数float threshold_;     // YOLO特有的参数public:YoloAdapter(int gpu_id = 0, float threshold = 0.5f): gpu_id_(gpu_id), threshold_(threshold) {}bool init(const std::string& model_path) override {// 适配初始化接口:将目标接口的参数转换为YOLO需要的参数return yolo_.loadModel(model_path, gpu_id_);}std::vector<DetectionResult> detect(const unsigned char* image_data, int width, int height) override {// 1. 调用YOLO的检测接口auto yolo_results = yolo_.runDetection(image_data, width, height, threshold_);// 2. 转换结果格式(YOLO格式 → 目标接口格式)std::vector<DetectionResult> results;for (const auto& yolo_res : yolo_results) {DetectionResult res;// 转换类别ID为类别名res.class_name = (yolo_res.class_id == 0) ? "car" : (yolo_res.class_id == 1) ? "pedestrian" : "unknown";// 转换边界框格式(x1,y1,x2,y2 → x,y,width,height)res.x = yolo_res.bbox[0];res.y = yolo_res.bbox[1];res.width = yolo_res.bbox[2] - yolo_res.bbox[0];res.height = yolo_res.bbox[3] - yolo_res.bbox[1];res.confidence = yolo_res.score;results.push_back(res);}return results;}std::string getName() const override {return "YOLO Detector (Adapted)";}
};// 适配器2:Faster R-CNN算法适配器
class FasterRCNNAdapter : public TargetDetector {
private:FasterRCNNAlgorithm frcnn_;  // 持有适配者对象std::string config_file_;    // Faster R-CNN特有的配置文件public:FasterRCNNAdapter(std::string config_file): config_file_(std::move(config_file)) {}bool init(const std::string& model_path) override {// 适配初始化接口:Faster R-CNN需要模型文件和配置文件frcnn_.initialize(model_path, config_file_);return true;  // FasterRCNNAlgorithm的initialize无返回值,默认成功}std::vector<DetectionResult> detect(const unsigned char* image_data, int width, int height) override {// 1. 调用Faster R-CNN的检测接口auto frcnn_results = frcnn_.detectObjects(image_data, width, height);// 2. 转换结果格式(Faster R-CNN格式 → 目标接口格式)std::vector<DetectionResult> results;for (const auto& frcnn_res : frcnn_results) {DetectionResult res;res.class_name = std::get<0>(frcnn_res);res.x = std::get<1>(frcnn_res);res.y = std::get<2>(frcnn_res);res.width = std::get<3>(frcnn_res);res.height = std::get<4>(frcnn_res);res.confidence = std::get<5>(frcnn_res);results.push_back(res);}return results;}std::string getName() const override {return "Faster R-CNN Detector (Adapted)";}
};// ------------------------------
// 客户端代码:智能驾驶感知系统
// ------------------------------
void runPerceptionSystem(TargetDetector& detector, const std::string& model_path) {// 初始化检测器(统一接口)if (!detector.init(model_path)) {std::cerr << "检测器初始化失败!\n";return;}std::cout << "\n运行检测器: " << detector.getName() << "\n";// 模拟输入图像数据(实际中是摄像头/激光雷达数据)unsigned char dummy_image[100 * 100] = {0};  // 占位图像数据// 执行检测(统一接口)auto results = detector.detect(dummy_image, 100, 100);// 输出检测结果std::cout << "检测到 " << results.size() << " 个目标:\n";for (const auto& res : results) {std::cout << "- " << res.class_name << " (置信度: " << res.confidence << "): "<< "位置(" << res.x << ", " << res.y << "), "<< "大小(" << res.width << "x" << res.height << ")\n";}
}int main() {// 1. 使用YOLO适配器YoloAdapter yolo_adapter(0, 0.6f);  // 指定GPU ID和阈值runPerceptionSystem(yolo_adapter, "yolo_model.pt");// 2. 使用Faster R-CNN适配器FasterRCNNAdapter frcnn_adapter("frcnn_config.yaml");  // 指定配置文件runPerceptionSystem(frcnn_adapter, "frcnn_model.pth");return 0;
}

代码解析
在智能驾驶感知系统的示例中,适配器模式解决了 “多算法接口不统一” 的核心问题:

1 目标接口(TargetDetector):
定义了感知系统需要的统一接口(init初始化、detect检测),所有检测器必须遵循此规范,确保系统上层代码(如决策模块)能统一调用。

2 适配者(YoloAlgorithm、FasterRCNNAlgorithm):
代表第三方算法,它们的接口各不相同:

    YOLO 需要loadModel(带 GPU ID)和runDetection(带阈值);Faster R-CNN 需要initialize(带配置文件)和detectObjects(返回格式不同)。

3 适配器(YoloAdapter、FasterRCNNAdapter):
实现TargetDetector接口,内部持有适配者对象,完成三项核心工作:

    接口转换:将init调用转换为适配者的初始化方法(如loadModel);参数适配:补充适配者需要的额外参数(如 YOLO 的 GPU ID、Faster R-CNN 的配置文件);数据转换:将适配者返回的检测结果(如 YOLO 的bbox[x1,y1,x2,y2])转换为系统统一的DetectionResult格式。

4 客户端(runPerceptionSystem):
仅依赖TargetDetector接口,无需关心具体算法的实现细节,实现了 “算法替换不影响上层代码” 的灵活性(如切换 YOLO 和 Faster R-CNN 时,客户端代码无需修改)。

3 迭代器模式

http://www.dtcms.com/a/456747.html

相关文章:

  • vite 怎么阻止某一页面的热更新
  • 邯郸网站设计做网站的一般尺寸
  • 【Linux系列】并发世界的基石:透彻理解 Linux 进程 — 进程优先级切换调度
  • 上海做网站技术做海报找素材网站
  • 全志 H3 armbian 备份
  • 【AI论文】DeepSearch:借助蒙特卡洛树搜索,以可验证奖励突破强化学习的瓶颈
  • 汽车信息安全新国标落地指南:GB 44496-2024测试验收实践
  • php网站怎么注入做网站都有备案吗
  • 大兴网站建设多少钱怎么建个网站
  • Java 大视界 -- Java 大数据机器学习模型在电商供应链库存协同管理与成本控制中的应用(421)
  • 【调研】加密货币/BTC/区块链的发展历史(2025)
  • 个人用云计算学习笔记 --20 (Nginx 服务器)
  • 【密码学实战】openHiTLS passwd命令行:专业密码哈希生成工具
  • form-data与x-www-form-urlencoded
  • 黑龙江省建设网官方网站中卫市平面设计培训学校
  • 《投资-105》价值投资者的认知升级与交易规则重构 - 如何从投资的角度看一下创业公司是否能够加入?你不是在找一份工作,你是在选择下一个5年的人生资产。
  • 前端梳理体系从常问问题去完善-框架篇(react生态)
  • 基于单片机的双档输出数字直流电压源设计
  • FastDDS
  • leetcode LCR.衣橱整理
  • 基于单片机的自动存包柜设计
  • 竞价关键词排名软件保山网站建设优化
  • 电力市场学习笔记(1):什么是电力现货交易
  • 单例模式:原理、实现与演进
  • 用AI帮忙,开发刷题小程序:微信小程序中实现Markdown图片解析与渲染功能详解
  • 天津魔方网站建设WordPress模板转换typecho
  • 小工具大体验:rlwrap加持下的Oracle/MySQL/SQL Server命令行交互
  • AI智能体的未来:从语言泛化到交互革命
  • 云计算划分标准与Kubernetes NetworkPolicy深度解析
  • 学院网站建设功能网络公关案例