C++ 设计模式之策略模式
【声明】本题目来源于卡码网(题目页面 (kamacoder.com))
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
【设计模式大纲】

【简介】什么是策略模式(第14种模式)
策略模式是⼀种⾏为型设计模式,它定义了⼀系列算法(这些算法完成的是相同的⼯作,只是实现不同),并将每个算法封装起来,使它们可以相互替换,⽽且算法的变化不会影响使⽤算法的客户。
举个例⼦,电商⽹站对于商品的折扣策略有不同的算法,⽐如新⽤户满减优惠,不同等级会员的打折情况不同,这种情况下会产⽣⼤量的if-else语句, 并且如果优惠政策修改时,还需要修改原来的代码,不符合开闭原则。
这就可以将不同的优惠算法封装成独⽴的类来避免⼤量的条件语句,如果新增优惠算法,可以添加新的策略类来实现,客户端在运⾏时选择不同的具体策略,⽽不必修改客户端代码改变优惠策略。

【基本结构】
策略模式包含下⾯⼏个结构:
- 策略类Strategy : 定义所有⽀持的算法的公共接⼝。
- 具体策略类ConcreteStrategy : 实现了策略接⼝,提供具体的算法实现。
- 上下⽂类Context : 包含⼀个策略实例,并在需要时调⽤策略对象的⽅法。

【简易实现】
下面利用Java代码对策略模式的实现流程作以说明:
1. 抽象策略类
abstract class Strategy {// 抽象⽅法public abstract void algorithmInterface();
}
2. 具体策略类1
// 2. 具体策略类1
class ConcreteStrategyA extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("Strategy A");// 具体的策略1执⾏逻辑}
}
3.具体策略类2
// 3. 具体策略类2
class ConcreteStrategyB extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("Strategy B");// 具体的策略2执⾏逻辑}
}
4. 上下文类
// 4. 上下⽂类
class Context {private Strategy strategy;// 设置具体的策略public Context(Strategy strategy) {this.strategy = strategy;}// 执⾏策略public void contextInterface() {strategy.algorithmlnterface();}
}
5. 客户端代码
// 5. 客户端代码
public class Main{public static void main(String[] args) {// 创建上下⽂对象,并设置具体的策略Context contextA = new Context(new ConcreteStrategyA());// 执⾏策略contextA.contextInterface();Context contextB = new Context(new ConcreteStrategyB());contextB.contextInterface();u}
}
【使用场景】
那什么时候可以考虑使⽤策略模式呢?
- 当⼀个系统根据业务场景需要动态地在⼏种算法中选择⼀种时,可以使⽤策略模式。例如,根据⽤户的⾏为选择不同的计费策略。
- 当代码中存在⼤量条件判断,条件判断的区别仅仅在于⾏为,也可以通过策略模式来消除这些条件语句。
在已有的⼯具库中,Java 标准库中的 Comparator 接⼝就使⽤了策略模式,通过实现这个接⼝,可以创建不同的⽐较器(指定不同的排序策略)来满⾜不同的排序需求。
【编码部分】
1. 题目描述
小明家的超市推出了不同的购物优惠策略,你可以根据自己的需求选择不同的优惠方式。其中,有两种主要的优惠策略:
1. 九折优惠策略:原价的90%。
2. 满减优惠策略:购物满一定金额时,可以享受相应的减免优惠。
具体的满减规则如下:
满100元减5元
满150元减15元
满200元减25元
满300元减40元
请你设计一个购物优惠系统,用户输入商品的原价和选择的优惠策略编号,系统输出计算后的价格。
2. 输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 20),表示需要计算优惠的次数。 接下来的 N 行,每行输入两个整数,第一个整数M( 0 < M < 400) 表示商品的价格, 第二个整数表示优惠策略,1表示九折优惠策略,2表示满减优惠策略;
3. 输出描述
每行输出一个数字,表示优惠后商品的价格;
4. C++ 编码实例
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file StrategyMode.hpp
* @brief 策略模式
* @autor 写代码的小恐龙er
* @date 2024/01/16
*/#include <iostream>
#include <string>
#include <vector>using namespace std;// 前置声明// 优惠策略的抽象接口类
class AbstractStrategy;// 优惠策略的具体实现类1 -- 打 九折
class StrategyNineDiscount;// 优惠策略的具体实现类2 -- 满减
class StrategyFullOut;// 上下文类 -- 调用优惠策略类
class DiscountContext;// 类的定义// 优惠策略的抽象接口类
class AbstractStrategy
{
// 接口函数
public:// 传入参数为 商品的原始价格 返回值为优惠后的价格virtual int ApplyDiscount(int originalPrice) = 0;
};// 优惠策略的具体实现类1 -- 打 九折
class StrategyNineDiscount : public AbstractStrategy
{
// 成员函数
public:StrategyNineDiscount(){}// 重载 优惠函数int ApplyDiscount(int originalPrice) override {return (int) (originalPrice * 0.9);}
};// 优惠策略的具体实现类2 -- 满减
class StrategyFullOut : public AbstractStrategy
{
// 成员数据
private:int _prices[4] = {100, 150, 200, 300};int _discounts[4] = {5, 15, 25, 40};
// 成员函数
public:StrategyFullOut(){}// 重载 优惠函数int ApplyDiscount(int originalPrice) override { // 从最大的优惠开始判断int length = sizeof(_prices) / sizeof(_prices[0]);for(int i = length - 1; i >= 0; i--){if(originalPrice >= _prices[i]){return originalPrice - _discounts[i];}}// 未达到满减优惠区间 return originalPrice;}
};// 上下文类 -- 调用优惠策略类
class DiscountContext
{
// 成员数据
private:AbstractStrategy *_strategy;
// 成员函数
public://通过传入策略基类来构造该类的实例DiscountContext(AbstractStrategy *strategy){this->_strategy = strategy;} // 管理优惠函数int ApplyDiscount(int originalPrice){ if(_strategy == nullptr) return 0;else return _strategy->ApplyDiscount(originalPrice);}
};int main()
{// 优惠次数int discountNum = 0;// 输入std::cin >> discountNum;// 构造上下文管理类DiscountContext *discountContext = nullptr;// 构造抽象策略类AbstractStrategy *strategy = nullptr;// 遍历输入所有的价格for(int i = 0; i < discountNum; i++){// 原始价格 和 优惠策略int originalPrice = 0;int discountType = 0;// 输入 std::cin >> originalPrice >> discountType;// 根据打折类型来操作if(discountType == 1){// 构造具体的优惠类strategy = new StrategyNineDiscount();}else if(discountType == 2){// 构造具体的优惠类strategy = new StrategyFullOut();}else std::cout << originalPrice << endl;discountContext = new DiscountContext(strategy);// 使用优惠函数originalPrice = discountContext->ApplyDiscount(originalPrice);std::cout<< originalPrice << endl;}// 析构if(strategy != nullptr){delete strategy;strategy = nullptr;}if(discountContext != nullptr){delete discountContext;discountContext = nullptr;}return 0;
}
......
To be continued.
相关文章:
C++ 设计模式之策略模式
【声明】本题目来源于卡码网(题目页面 (kamacoder.com)) 【提示:如果不想看文字介绍,可以直接跳转到C编码部分】 【设计模式大纲】 【简介】什么是策略模式(第14种模式) 策略模式是⼀种⾏为型设计模式&…...
(202401)深度强化学习基础2:策略梯度
文章目录 前言策略梯度1 基于价值算法的缺点2 策略梯度算法3 REINFORCE算法本章小结 前言 感谢Datawhale成员的开源本次学习内容的文档地址为 第九章 策略梯度 策略梯度 这个章节会开始介绍基于策略梯度的算法。前面的算法都是针对“奖励”或者说“回报(reward&a…...
bgp大AS小AS选路-联邦ebgp选路
效果图:R1 ping 通 R8 环回 R4的bgp路由表中5.5.5.5通过修改起源属性,下一跳R7变为R2, 即原本走下面R4-R7-R6-R5,改成R4-R3-R2-R5 R5效果图和R4类似(不放了),R5的bgp路由表中4.4.4.4下一跳从R2优先改为R7优先(即原本走上面路R4-R3-R2-R5,改成下面路R4-R7-R6-R5),通…...
beego API 自动化文档
API 全局设置 必须设置在 routers/router.go 中,文件的注释,最顶部: // APIVersion 1.0.0 // Title mobile API // Description mobile has every tool to get any job done, so codename for the new mobile APIs. // Contact astaxiegmai…...
百度搜索Push个性化:新的突破
作者 | 通用搜索产品研发组 导读 本文简单介绍了百度搜索Push个性化的发展过程,揭示了面临的困境和挑战:如何筛选优质物料、如何对用户精准推荐等。我们实施了一系列策略方法进行突破,提出核心的解决思路和切实可行的落地方案。提升了搜索DAU…...
【Oracle】ORA-32017和ORA-00384错误处理
文章目录 【Oracle】ORA-32017和ORA-00384错误处理问题描述问题原因和解决测试验证 【声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和数据库技术(ID:SQLplusDB) 收集Oracle数据库内存相关的信息 【Oracle】ORA-32017和ORA-00384错误…...
MySQL三大日志
1. redo log 1.1 特点 InnoDB存储引擎独有物理日志,记录在数据页上做的修改让MySQL拥有了崩溃恢复能力,保证事务的持久性 1.2 刷盘时机 事务提交时log buffer 空间使用大约一半时事务日志缓冲区满InnoDB 定期执行检查点Checkpoint后台刷新线程&#…...
力扣每日一练(24-1-20)
大脑里的第一想法是排列组合,直接给出超级准确的最优解。 但不适用,hhh 只要连续的n个元素大于或者等于target就可以了 题目比自己想象的要好解决 解法是使用滑动窗口算法。这个算法的基本思想是维护一个窗口,使得窗口内的元素总和大于等于目…...
Pytest系列(2) - assert断言详细使用
前言 与unittest不同,pytest使用的是python自带的assert关键字来进行断言assert关键字后面可以接一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败 assert小栗子 想在抛出异常之…...
CodeWave智能开发平台--03--目标:应用创建--10初级采购管理系统总结
摘要 本文是网易数帆CodeWave智能开发平台系列的第14篇,主要介绍了基于CodeWave平台文档的新手入门进行学习,实现一个完整的应用,本文主要完成10初级采购管理系统总结 CodeWave智能开发平台的14次接触 CodeWave参考资源 网易数帆CodeWave…...
外包干了4个月,技术退步明显.......
先说一下自己的情况,大专生,18年通过校招进入武汉某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…...
图片批量建码怎么用?每张图片快速生成二维码
当我们需要给每个人分别下发对应的个人证件类图片信息,比如制作工牌、荣誉展示或者负责人信息展示时,现在都开始使用二维码的方法来展示员工信息。那么如何快速将每个人员的信息图片分别制作成二维码图片呢,最简单的方法就是使用图片批量建码…...
时间复杂度的排序
在计算机科学中,不同的算法有不同的时间复杂度。以下是一些常见的时间复杂度,并按照它们的增长速度从低到高排序: O(1) - 常数时间复杂度: 表示算法的执行时间是固定的,不随输入规模的增加而变化。例如,直接…...
js控制浏览器前进、后退、页面跳转
在JavaScript中,你可以使用 window 对象的 history 对象来控制浏览器的历史记录。以下是一些常用的方法: 前进和后退: window.history.forward(): 前进到历史记录中的下一个页面。window.history.back(): 返回历史记录中的上一个页面。window…...
【长文阅读】MAMBA作者博士论文<MODELING SEQUENCES WITH STRUCTURED STATE SPACES>-Chapter1
Gu A. Modeling Sequences with Structured State Spaces[D]. Stanford University, 2023. 本文是MAMBA作者的博士毕业论文,为了理清楚MAMBA专门花时间拜读这篇长达330页的博士论文,由于知识水平有限,只能尽自己所能概述记录,并适…...
Unity3D学习之UI系统——GUI
文章目录 1. 前言2. 工作原理和主要作用3. 基础控件3.1 重要参数及文本和按钮3.1.1 GUI 共同点3.1.2 文本控件3.1.3 按钮控件 3.2 多选框和单选框3.2.1 多选框3.2.2 单选框3.2.3 输入框3.2.4 拖动条 3.3 图片绘制和框3.3.1 图片3.3.2 框绘制 4 工具栏和选择网格4.1 工具栏4.2 选…...
用户ssh正确密码登陆均报错Permission denied, please try again.处理方法
我的一台虚拟机IP是:192.168.59.133任何服务器使用任何用户ssh均报错,甚至连自己都不能ssh自己。 不能使用任何工具连接上该服务器 使用ssh连接自己的127.0.0.1和localhost都权限拒绝错误 ssh报错如下 任何服务器ssh报错内容均一样:报错内…...
IO、NIO、IO多路复用
IO是什么? IO分为两类,它们之间是有区别的,而且有很大的区别;1. 文件系统的IO 也叫本地io,就是和磁盘或者外围存储设备进行读写操作,外围设备有USB、移动硬盘等等;2. 网络的IO 将数据发送给对方…...
探索FTP:原理、实践与安全优化
引言 在正式开始讲解之前,首先来了解一下文件存储的类型有哪些。 DAS、SAN和NAS是三种不同的存储架构,分别用于解决不同场景下的数据存储需求。 DAS (Direct Attached Storage 直接附加存储):DAS 是指将存储设备(如硬盘&#x…...
git中的语法和术语含义
目录 第一章、git常用术语1.1)文件状态1.2)git常用术语的含义 第二章、git文件状态解析2.1)从git init开始:Untracked(未跟踪)2.2)git add fileName后:Staged(已暂存&…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
