C++实现设计模式---策略模式 (Strategy)

embedded/2025/1/16 6:53:56/

策略模式 (Strategy)

策略模式 是一种行为型设计模式,它定义了一系列算法,并将每种算法封装到独立的类中,使得它们可以相互替换。策略模式让算法的变化不会影响使用算法的客户端。


意图

  • 将算法的定义与使用分离。
  • 通过封装和组合的方式,使得算法可以灵活替换。

使用场景

  1. 系统需要动态选择算法

    • 需要在运行时根据条件选择不同的算法实现。
  2. 避免使用大量条件语句

    • 如果系统中有大量的 if-elseswitch 语句,可以使用策略模式将这些条件逻辑封装为独立的策略类。
  3. 算法需要灵活扩展

    • 新增算法时无需修改客户端代码,只需实现新的策略类即可。

参与者角色

  1. 上下文类 (Context)

    • 持有对策略对象的引用,并通过策略接口调用具体策略的方法。
  2. 策略接口 (Strategy)

    • 定义了所有具体策略的公共接口。
  3. 具体策略类 (ConcreteStrategy)

    • 实现策略接口,封装具体的算法逻辑。

示例代码

以下代码展示了策略模式的实现,用于计算不同折扣策略下的商品价格。

#include <iostream>
#include <memory>// 策略接口:折扣策略
class DiscountStrategy {
public:virtual ~DiscountStrategy() = default;virtual double calculatePrice(double originalPrice) const = 0; // 计算折后价格
};// 具体策略类:无折扣
class NoDiscount : public DiscountStrategy {
public:double calculatePrice(double originalPrice) const override {return originalPrice; // 无折扣,返回原价}
};// 具体策略类:百分比折扣
class PercentageDiscount : public DiscountStrategy {
private:double discountRate; // 折扣率public:PercentageDiscount(double rate) : discountRate(rate) {}double calculatePrice(double originalPrice) const override {return originalPrice * (1 - discountRate); // 按折扣率计算}
};// 具体策略类:固定金额折扣
class FixedAmountDiscount : public DiscountStrategy {
private:double discountAmount; // 折扣金额public:FixedAmountDiscount(double amount) : discountAmount(amount) {}double calculatePrice(double originalPrice) const override {return (originalPrice > discountAmount) ? (originalPrice - discountAmount) : 0; // 不低于0元}
};// 上下文类:价格计算器
class PriceCalculator {
private:std::unique_ptr<DiscountStrategy> strategy; // 策略对象public:void setStrategy(std::unique_ptr<DiscountStrategy> newStrategy) {strategy = std::move(newStrategy); // 动态设置策略}double calculate(double originalPrice) const {if (strategy) {return strategy->calculatePrice(originalPrice); // 调用策略计算价格} else {throw std::runtime_error("No strategy set!");}}
};// 客户端代码
int main() {PriceCalculator calculator;// 设置无折扣策略calculator.setStrategy(std::make_unique<NoDiscount>());std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;// 设置百分比折扣策略calculator.setStrategy(std::make_unique<PercentageDiscount>(0.2)); // 20% 折扣std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;// 设置固定金额折扣策略calculator.setStrategy(std::make_unique<FixedAmountDiscount>(30)); // 减30元std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;return 0;
}

代码解析

1. 策略接口 (DiscountStrategy)
  • 定义了计算折扣价格的接口:
class DiscountStrategy {
public:virtual ~DiscountStrategy() = default;virtual double calculatePrice(double originalPrice) const = 0;
};
2. 具体策略类
  • 每个具体策略类实现了 DiscountStrategy 接口,封装了具体的算法逻辑:
class PercentageDiscount : public DiscountStrategy {
private:double discountRate;public:PercentageDiscount(double rate) : discountRate(rate) {}double calculatePrice(double originalPrice) const override {return originalPrice * (1 - discountRate);}
};
3. 上下文类 (PriceCalculator)
  • PriceCalculator 类持有对策略对象的引用,负责调用策略的 calculatePrice 方法:
class PriceCalculator {
private:std::unique_ptr<DiscountStrategy> strategy;public:void setStrategy(std::unique_ptr<DiscountStrategy> newStrategy) {strategy = std::move(newStrategy);}double calculate(double originalPrice) const {if (strategy) {return strategy->calculatePrice(originalPrice);} else {throw std::runtime_error("No strategy set!");}}
};
4. 客户端
  • 客户端通过上下文类设置不同的策略对象,实现动态切换算法:
calculator.setStrategy(std::make_unique<NoDiscount>());
std::cout << "Final Price: $" << calculator.calculate(100) << std::endl;calculator.setStrategy(std::make_unique<PercentageDiscount>(0.2));
std::cout << "Final Price: $" << calculator.calculate(100) << std::endl;

优缺点

优点
  1. 算法独立
    • 每种算法封装在独立的类中,易于扩展和维护。
  2. 动态切换
    • 可以在运行时灵活替换算法,而无需修改客户端代码。
  3. 消除条件语句
    • 避免了大量的 if-elseswitch 语句。
缺点
  1. 增加系统复杂性
    • 每种策略需要定义一个类,可能增加系统的类数量。
  2. 客户端必须了解策略
    • 客户端需要知道有哪些策略可用,并显式设置策略。

适用场景

  1. 系统中有多种算法可以选择

    • 如排序算法、折扣计算、加密算法等。
  2. 需要动态切换算法

    • 在运行时根据条件选择最优的算法。
  3. 消除条件判断

    • 当系统中有大量的条件分支时,可以使用策略模式将分支逻辑替换为独立的策略类。

总结

策略模式通过将算法封装为独立的类,使得算法可以灵活切换并独立扩展。它是一种非常灵活的设计模式,特别适用于需要动态选择算法的场景。


http://www.ppmy.cn/embedded/154329.html

相关文章

matlab使用 BP 神经网络进行数据预测的完整流程,包括数据读取、数据预处理等等

%% 初始化程序 warning off % 关闭报警信息 close all % 关闭所有图窗 clear % 清空变量 clc % 清空命令行 setdemorandstream(172) %设置随机种子为1%% 读取数据 data xlsread(Y.xlsx); %% 划分训练集…

HAL库 SPI+DMA接收 通讯速率高就读取失败

最近在写一个读取ad7691数据的驱动时&#xff0c;SPI2设置为Receive only master模式&#xff0c;此时发现用SPIDMA的HAL库函数HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)接收数据时&#xff08;DMA为normal模式&#xff0c;以字节单位传输…

vim使用指南

&#x1f3dd;️专栏&#xff1a;计算机操作系统 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 一、Vim 的基本概念 1.1普通模式 (Normal Mode) 1.2插入模式 (Insert Mode) 1.3命令模…

Vue3使用vue-count-to数字滚动模块报错解决方案

小伙伴们是不是遇到了vue3项目使用vue-count-to出现报错的问题 报错如下&#xff1a; TypeError: Cannot read properties of undefined (reading _c) 这个错误信息具体是说没读取到_c的属性 具体不清楚是什么原因&#xff0c;排查还得去看源码&#xff0c;所以我们来解决&a…

hot100_240. 搜索二维矩阵 II

hot100_240. 搜索二维矩阵 II 直接遍历列减行增 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,1…

【精选】基于EfficientViT优化YOLOv8的智能车辆识别系统设计 车辆颜色分类与车牌检测、深度学习目标检测系统开发

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

(12)springMVC文件的上传

SpringMVC文件上传 首先是快速搭建一个springMVC项目 新建项目mvn依赖导入添加webMoudle添加Tomcat运行环境.在配置tomcat时ApplicationContext置为"/"配置Artfact的lib配置WEB-INF配置文件&#xff08;记得添加乱码过滤&#xff09;配置springmvc-servlet文件&…

Vue2+OpenLayers给标点Feature添加信息窗体(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、信息窗体DOM元素 3.2、创建Overlay 3.3、创建一个点 3.4、给点初始化点击事件 3.5、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 初始化变量&#xff1a; d…