重温设计模式--13、策略模式

策略模式介绍

文章目录

      • 策略模式介绍
      • C++ 代码示例

策略模式是一种行为设计模式,它允许在运行时选择算法的行为。该模式将算法的定义和使用分离开来,使得算法可以独立于使用它的客户端而变化,提高了代码的灵活性和可维护性。
在这里插入图片描述

其主要包含以下几个角色:

  1. 抽象策略(Strategy):定义了一个公共接口,用于所有具体策略类实现,这个接口声明了算法的方法签名,客户端通过这个接口来调用具体的算法。
  2. 具体策略(Concrete Strategy):实现了抽象策略接口,提供具体的算法实现逻辑。不同的具体策略类实现了不同的算法,可以根据具体需求进行替换。
  3. 上下文(Context):持有一个对抽象策略的引用,通过这个引用调用具体策略的算法方法。上下文类负责与客户端交互,并根据情况决定使用哪个具体策略。

使用策略模式的好处在于:

  • 可扩展性强:当需要添加新的算法时,只需创建新的具体策略类实现抽象策略接口即可,不需要修改现有代码的核心逻辑,符合开闭原则(对扩展开放,对修改关闭)。
  • 代码复用性高:具体策略类可以在不同的上下文中被复用,只要符合抽象策略定义的接口规范就行。
  • 便于维护和测试:由于每个算法都独立在具体策略类中实现,代码结构清晰,便于单独对各个算法进行维护和测试。

C++ 代码示例

以下是一个简单的用 C++ 实现的策略模式示例,模拟一个电商系统中不同的折扣策略计算商品最终价格的场景。

#include <iostream>
#include <string>// 抽象策略类,定义折扣计算的接口
class DiscountStrategy {
public:virtual double calculateDiscount(double price) = 0;virtual ~DiscountStrategy() {}
};// 具体策略类1:满减折扣策略
class FullReductionStrategy : public DiscountStrategy {
public:double calculateDiscount(double price) override {if (price >= 200) {return price * 0.2;  // 满200减20%}return 0;}
};// 具体策略类2:固定折扣策略
class FixedDiscountStrategy : public DiscountStrategy {
public:double calculateDiscount(double price) override {return price * 0.1;  // 固定打9折}
};// 上下文类,持有折扣策略引用并执行折扣计算
class ShoppingCart {
public:ShoppingCart(DiscountStrategy* strategy) : m_strategy(strategy) {}void setDiscountStrategy(DiscountStrategy* strategy) {m_strategy = strategy;}double calculateFinalPrice(double price) {double discount = m_strategy->calculateDiscount(price);return price - discount;}private:DiscountStrategy* m_strategy;
};int main() {// 创建具体策略对象FullReductionStrategy fullReduction;FixedDiscountStrategy fixedDiscount;// 创建上下文对象,并传入具体策略对象ShoppingCart cart1(&fullReduction);ShoppingCart cart2(&fixedDiscount);double price = 300;std::cout << "使用满减策略,商品价格为 " << price << " 时,最终价格: " << cart1.calculateFinalPrice(price) << std::endl;std::cout << "使用固定折扣策略,商品价格为 " << price << " 时,最终价格: " << cart2.calculateFinalPrice(price) << std::endl;// 更换策略并重新计算价格cart1.setDiscountStrategy(&fixedDiscount);std::cout << "更换为固定折扣策略后,商品价格为 " << price << " 时,最终价格: " << cart1.calculateFinalPrice(price) << std::endl;return 0;
}

下面对上述代码进行详细解释:

  1. 抽象策略类 DiscountStrategy

    • 它定义了一个纯虚函数 calculateDiscount,这个函数接收商品价格作为参数,用于计算折扣金额,返回值是折扣的具体数值(以价格的比例形式体现)。纯虚函数的存在使得这个类成为抽象类,不能直接实例化,必须由具体的子类来实现其 calculateDiscount 方法。
    • 虚析构函数 ~DiscountStrategy() 的定义是为了保证在通过基类指针删除派生类对象时能够正确调用派生类的析构函数,避免内存泄漏等问题,遵循了多态情况下正确析构的原则。
  2. 具体策略类

    • FullReductionStrategy:实现了 DiscountStrategy 抽象策略接口,在 calculateDiscount 方法中定义了满减的折扣逻辑,即当商品价格大于等于200时,给予20%的折扣,否则没有折扣(返回0)。
    • FixedDiscountStrategy:同样实现了抽象接口,其折扣逻辑是固定给予商品价格10%的折扣,无论商品价格具体是多少。
  3. 上下文类 ShoppingCart

    • 它有一个私有成员变量 m_strategy,类型是指向 DiscountStrategy 抽象策略类的指针,通过构造函数或者 setDiscountStrategy 方法来初始化或更换这个指针所指向的具体策略对象。
    • calculateFinalPrice 方法用于根据当前持有的具体策略计算商品的最终价格,它先调用 m_strategy 指向的具体策略对象的 calculateDiscount 方法获取折扣金额,然后用商品原价减去折扣金额得到最终价格。
  4. main 函数部分

    • 首先创建了两个具体策略类的对象 fullReduction(满减策略)和 fixedDiscount(固定折扣策略)。
    • 接着创建了两个 ShoppingCart 上下文对象 cart1cart2,并分别在构造函数中传入不同的具体策略对象,这样 cart1 初始使用满减策略,cart2 使用固定折扣策略。然后通过调用 calculateFinalPrice 方法分别计算并展示了商品价格为300时,不同策略下的最终价格。
    • 之后又通过 cart1setDiscountStrategy 方法将其使用的策略更换为固定折扣策略,并再次计算和展示了最终价格,体现了策略模式可以在运行时灵活切换算法(策略)的特点。

通过这个示例可以看到,策略模式将不同的折扣算法封装在各自的具体策略类中,而 ShoppingCart 上下文类只需要关心抽象策略接口,根据具体情况使用不同的具体策略来计算最终价格,使得代码结构清晰,易于扩展和维护。例如,如果后续要添加一个新的折扣策略(如会员专享折扣策略等),只需要创建一个新的具体策略类实现 DiscountStrategy 接口,并在需要的地方(如 ShoppingCart 上下文对象中)使用这个新策略即可,不需要修改原有的核心代码逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/65363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【GOOD】A Survey of Deep Graph Learning under Distribution Shifts

深度图学习在分布偏移下的综述&#xff1a;从图的分布外泛化到自适应 Northwestern University, USA Repository Abstract 图上的分布变化——训练和使用图机器学习模型之间的数据分布差异——在现实世界中普遍存在&#xff0c;并且通常不可避免。这些变化可能会严重恶化模…

【Axure高保真原型】环形进度条(开始暂停效果)

今天和大家分享环形进度条&#xff08;开始暂停效果&#xff09;的原型模版&#xff0c;效果包括&#xff1a; 点击开始按钮&#xff0c;可以环形进度条开始读取&#xff0c;中部百分比显示环形的读取进度&#xff1b; 在读取过程中&#xff0c;点击暂停按钮&#xff0c;可以随…

Euler 21.10(华为欧拉)安装oracle19c-RAC

1. Euler 21.10安装oracle19c-RAC 1.1. 环境规划 1.1.1. 主机规划 hostname IP 实例名 hfdb90 192.168.40.90 hfdb1 hfdb91 192.168.40.90 hfdb2 系统版本 BigCloud Enterprise Linux For Euler 21.10 (GNU/Linux 4.19.90-2107.6.0.0100.oe1.bclinux.x86_64 x86_6…

【python】matplotlib(radar chart)

文章目录 1、功能描述和原理介绍2、代码实现3、效果展示4、完整代码5、多个雷达图绘制在一张图上6、参考 1、功能描述和原理介绍 基于 matplotlib 实现雷达图的绘制 一、雷达图的基本概念 雷达图&#xff08;Radar Chart&#xff09;&#xff0c;也被称为蛛网图或星型图&…

Business Cooperation Process

Business Cooperation Process 商务合作基本流程 并不是每个人都能做到言而有信的&#xff0c;因此还是需要流程来约束的。

模式识别-Ch2-分类错误率

分类错误率 最小错误率贝叶斯决策 样本 x x x的错误率&#xff1a; 任一决策都可能会有错误。 P ( error ∣ x ) { P ( w 2 ∣ x ) , if we decide x as w 1 P ( w 1 ∣ x ) , if we decide x as w 2 P(\text{error}|\mathbf{x})\begin{cases} P(w_2|\mathbf{x}), &…

Milvus×全诊通:从导诊到智能超声,如何将人效比翻倍

AI与智慧医疗的结合已是未来发展的必然趋势。近年来&#xff0c;国家卫健委推崇智慧医疗和AI技术&#xff0c;如智能导诊、预问诊、辅助诊断等&#xff0c;以提高医疗服务效率和诊断准确性&#xff0c;改善患者就医体验。 全诊通是一家专注于医疗SaaS和人工智能的公司&#xff…

自动驾驶相关知识学习笔记

一、概要 因为想知道SIL、HIL是什么仿真工具&#xff0c;故而浏览了自动驾驶相关的知识。 资料来源《自动驾驶——人工智能理论与实践》胡波 林青 陈强 著&#xff1b;出版时间&#xff1a;2023年3月 二、图像的分类、分割与检测任务区别 如图所示&#xff0c;这些更高阶的…

springcloud 介绍

Spring Cloud是一个基于Spring Boot的微服务架构解决方案集合&#xff0c;它提供了一套完整的工具集&#xff0c;用于快速构建分布式系统。在Spring Cloud的架构中&#xff0c;服务被拆分为一系列小型、自治的微服务&#xff0c;每个服务运行在其独立的进程中&#xff0c;并通过…

【PLL】非线性瞬态性能

频率捕获、跟踪响应&#xff0c;是大信号非线性行为锁相范围内的相位、频率跟踪&#xff0c;不是非线性行为 所以&#xff1a;跟踪&#xff0c;是线性区域&#xff1b;捕获&#xff0c;是大信号、非线性区域 锁定范围&#xff1a;没有周跳&#xff08;cycle-slipping&#xff0…

QML学习(七) 学习QML时,用好Qt设计器,快速了解各个组件的属性

在初步学习QML时&#xff0c;特别建议看看Qt设计器&#xff0c;先利用Qt Quick设计师的使用&#xff0c;快速的对Qt Quick的各个组件及其常用的属性&#xff0c;有个初步的了解和认识。如果初始学习一上来直接以代码形式开干&#xff0c;很容易一头雾水。而设计器以最直白的所见…

find 查找文件grep匹配数据

一、find介绍 1. find . -iname "*.txt"查找当前目录下各个文件夹下的txt属性的文件(i忽略大小写)。 2.find . -type f 查找当前目录下各个文件夹下的文件 3.find . -type d 查找当前目录下各个文件夹下的目录 4.find . -type f | xargs grep -ain -E "匹配…

Mac上鸿蒙配置HDC报错:zsh: command not found: hdc -v

这个问题困扰了好久&#xff0c;按照官方文档去配置的&#xff0c;就是会一直报错&#xff0c;没有配置成功&#xff0c;主要原因是官网ide的路径可能和你本地的ide的路径不一致&#xff0c;因为官网的ide版本可能是最新的 一.先查找你本地的toolchains目录在哪里&#xff0c;…

CS·GO搬砖流程详细版

说简单点&#xff0c;就是Steam买了然后BUFF上卖&#xff0c;或许大家都知道这点&#xff0c;但就是一些操作和细节问题没那么明白。我相信&#xff0c;你看完这篇文章以后&#xff0c;至少会有新的认知。 好吧&#xff0c;废话少说&#xff0c;直接上实操&#xff01; 首先准…

“深入浅出”系列之FFmpeg:(1)音视频开发基础

我的音视频开发大部分内容是跟着雷霄骅大佬学习的&#xff0c;所以笔记也是跟雷老师的博客写的。 一、音视频相关的基础知识 首先播放一个视频文件的流程如下所示&#xff1a; FFmpeg的作用就是将H.264格式的数据转换成YUV格式的数据&#xff0c;然后SDL将YUV显示到电脑屏幕上…

【Linux】Linux开发:GDB调试器与Git版本控制工具指南

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建 在 Linux 开发中&#xff0c;GDB 调试器和 Git 版本控制工具是开发者必备的利器。GDB 帮助快速定位代码问题&#xff0c;G…

【设计模式-2】23 种设计模式的分类和功能

在软件工程领域&#xff0c;设计模式是解决常见设计问题的经典方案。1994 年&#xff0c;Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides&#xff08;四人帮&#xff0c;GoF&#xff09;在《设计模式&#xff1a;可复用面向对象软件的基础》一书中系统性地总结了…

谷粒商城-高级篇完结-Sleuth+Zipkin 服务链路追踪

1、基本概念和整合 1.1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位 。主要体现在&#…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

实际开发中,常见pdf|word|excel等文件的预览和下载

实际开发中,常见pdf|word|excel等文件的预览和下载 背景相关类型数据之间的转换1、File转Blob2、File转ArrayBuffer3、Blob转ArrayBuffer4、Blob转File5、ArrayBuffer转Blob6、ArrayBuffer转File 根据Blob/File类型生成可预览的Base64地址基于Blob类型的各种文件的下载各种类型…