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

ops/2025/1/16 4:39:50/

策略模式 (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/ops/150466.html

相关文章

【Linux】正则表达式

正则表达式是一种可供Linux工具过滤文本的自定义模板&#xff0c;Linux工具&#xff08;如sed、gawk&#xff09;会在读取数据时使用正则表达式对数据进行模式匹配。 正则表达式使用元字符来描述数据流中的一个或多个字符。它是由正则表达式引擎实现的。正则表达式引擎是一种底…

mysql 双主双从 + proxysql 代理

环境 主机ipmaster1192.168.233.101master2192.168.233.102slave1192.168.233.103slave2192.168.233.104client192.168.233.105 需求 master1和master2互为主从&#xff0c;slave1是master1的从&#xff0c;slave2是master2的从。 master主机通过proxysql代理实现负载均衡的…

【工具箱】GitHub命令行访问配置

文章目录 配置SSH访问配置个人访问令牌&#xff08;代替原密码&#xff09;GitHub Desktop其它 GitHub是编程社区广泛使用的产品&#xff0c;它的使用范围已经扩展到很多需要多版本控制的系统中了。本文介绍配置 GitHub 的本地访问的方法&#xff0c;以及图形化界面&#xff08…

【STM32】LED状态翻转函数

1.利用状态标志位控制LED状态翻转 在平常编写LED状态翻转函数时&#xff0c;通常利用状态标志位实现LED状态的翻转。如下所示&#xff1a; unsigned char led_turn_flag; //LED状态标志位&#xff0c;1-点亮&#xff0c;0-熄灭/***************************************函…

阿里云-Centos9-安装Docker-配置镜像拉取加速地址-开机自启

阿里云-Centos9-安装Docker-配置镜像拉取加速地址-开机自启 更新镜像源安装环境配置加速卸载安装pull拉取加速开机自启 更新镜像源 # dnf update&#xff1a;更新所有已安装的软件包。 sudo dnf update -y安装环境 # 安装环境 # yum-utils&#xff1a;提供了管理yum仓库的工具。…

手机与平板:勒索软件的“天然通道”

过去的两年中&#xff0c;63%的企业曾遭受勒索软件攻击。 随着全球媒体频频报道勒索软件威胁&#xff0c;这一话题引发了广泛关注。虽然勒索软件并非新生事物&#xff0c;但其受网络犯罪分子“青睐”的趋势却愈发显著。 为什么手机和平板成了目标&#xff1f; 当前&#xff0c…

2024年开发语言热度排名

随着技术的不断发展和变化&#xff0c;编程语言的热度也在不断演变。2024年即将到来&#xff0c;我们有必要回顾和展望当前和未来的开发语言市场。本文将基于多个因素&#xff0c;包括行业需求、社区支持、流行度以及新兴趋势&#xff0c;对2024年的开发语言热度进行排名和分析…

C#,动态规划问题中基于单词搜索树(Trie Tree)的单词断句分词( Word Breaker)算法与源代码

1 分词 分词是自然语言处理的基础&#xff0c;分词准确度直接决定了后面的词性标注、句法分析、词向量以及文本分析的质量。英文语句使用空格将单词进行分隔&#xff0c;除了某些特定词&#xff0c;如how many&#xff0c;New York等外&#xff0c;大部分情况下不需要考虑分词…