策略模式【行为模式C++】
1.概述
策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
策略模式通常应用于需要多种算法进行操作的场景,如排序、搜索、数据压缩等。在这些情况下,不同的算法有不同的优缺点和适用性,因此需要进行选择。
通过使用策略模式,我们可以轻松地切换算法,而无需修改客户端代码。这使得代码更加灵活、可扩展、易于维护,减少了重复的代码,并提高了代码的可读性。
2.结构
策略模式的结构包括以下几个部分:
抽象策略(Strategy)类:定义所有支持的算法或行为的公共接口或抽象类。
具体策略(Concrete Strategy)类:实现抽象策略接口,提供具体的算法或行为。
环境(Context)类:持有一个对抽象策略的引用,并且通过该引用调用具体策略类中实现的算法或行为。
在策略模式中,客户端代码仅与环境类及其抽象策略接口交互,无需关心具体实现细节。当需要更改算法或行为时,只需要修改具体策略类即可,而无需修改客户端代码或其他策略类。
3.实现
3.1 实例类比
假如你需要前往机场。 你可以选择乘坐公共汽车、 预约出租车或骑自行车。 这些就是你的出行策略。 你可以根据预算或时间等因素来选择其中一种策略。
3.2 实例引入
在支付系统中,我们就可以使用策略模式,针对不同的支付方式封装成不同的策略类。每个策略类负责实现一个特定的支付方式,并提供相应的算法来处理付款。这样,客户端代码就可以通过选择不同的策略类来实现不同的支付方式,而无需了解每种支付方式的具体实现细节。
例如,假设我们使用xx宝,可用银行卡、微信支付和支付宝支付三种支付方式。每种支付方式都有自己的实现方式和规则,但客户端并不需要知道支付方式的具体实现,只需要选择一个支付策略即可。这时候,我们可以使用策略模式来实现支付系统,将每种支付方式封装成一个支付策略类,让客户端根据需要选择不同的支付策略类。
3.3 结构分析
在这个案例中,代码中的各个结构可以对应到策略模式中的不同角色:
- Context(上下文):对应代码中的PaymentContext类,负责调用具体支付策略对象的付款方法。
- Strategy(策略):对应代码中的PaymentStrategy接口,定义了所有支持的支付方式的公共接口。
- ConcreteStrategy(具体策略):对应代码中的BankCardStrategy、WeChatPayStrategy和AliPayStrategy类,实现了PaymentStrategy接口,提供了不同的支付方式实现逻辑。
类图如下:
3.4 具体实现
#include <iostream>
#include <string>using namespace std;//抽象策略
class PaymentStrategy {
public:virtual void pay(double money) = 0;
};//具体策略
/*** 银联支付*/
class BankCardStrategy :public PaymentStrategy {
private:/** 银行卡卡号 */string cardNumber;/** 银行卡有效期 */string expiryDate;public:BankCardStrategy(string cardNumber, string expiryDate) {this->cardNumber = cardNumber;this->expiryDate = expiryDate;}void pay(double money) {// 基于卡的付款逻辑std::cout << "使用银联支付:"<< money <<"元" << endl;}
};/*** 微信*/
class WeChatPayStrategy :public PaymentStrategy {
private:/** 微信openId */string openId;public:WeChatPayStrategy(string openId) {this->openId = openId;}void pay(double money) {// 基于微信支付的付款逻辑std::cout << "使用微信支付:" << money << "元" << endl;}
};/*** 支付宝*/
class AliPayStrategy :public PaymentStrategy {
private:string account;string password;public:AliPayStrategy(string account, string password) {this->account = account;this->password = password;}void pay(double money) {// 基于支付宝的付款逻辑std::cout << "使用支付宝支付:" <<money << "元" << endl;}
};class PaymentContext {
private:PaymentStrategy *_paymentStrategy;public:void setPaymentStrategy(PaymentStrategy* paymentStrategy) {_paymentStrategy = paymentStrategy;}void pay(double money) {if (_paymentStrategy == nullptr) {throw std::runtime_error("支付策略不能为空");}_paymentStrategy->pay(money);}
};int main()
{std::cout << "策略模式........" << endl;// 创建一个银联支付策略对象BankCardStrategy *bankCardStrategy = new BankCardStrategy("014600002206", "20224-12");// 创建一个微信支付策略对象WeChatPayStrategy *weChatPayStrategy = new WeChatPayStrategy("GoWJW");// 创建一个支付宝支付策略对象AliPayStrategy *aliPayStrategy = new AliPayStrategy("alipayaccount@gowjw.com", "alipaypassword");// 创建一个支付上下文对象PaymentContext *paymentContext = new PaymentContext();// 使用银联支付paymentContext->setPaymentStrategy(bankCardStrategy);paymentContext->pay(2024.4);// 使用微信支付paymentContext->setPaymentStrategy(weChatPayStrategy);paymentContext->pay(2024.4);// 使用支付宝支付paymentContext->setPaymentStrategy(aliPayStrategy);paymentContext->pay(2024.4);return 0;
}
3.5 运行结果
4.策略优缺点
策略模式主要优点和缺点如下:
优点:
- 策略模式使得各种算法可以在不修改原有代码的情况下替换或者新增,提高了代码的可扩展性和可维护性;
- 策略模式将算法的实现从上下文中解耦出来,使得算法可以独立进行单元测试;
- 策略模式符合开闭原则,即对扩展开放,对修改关闭,可以通过增加新的策略类来扩展应用,而无需修改原有代码。
缺点:
- 如果策略数量过多,会导致类数量增加,增加系统的复杂度;
- 客户端需要知道所有的策略类,并选择合适的策略类,这可能会导致客户端代码较为复杂;
- 策略模式将算法的实现从上下文中解耦出来,同时也意味着上下文不能控制策略的执行顺序,需要客户端自行控制执行顺序。
5.应用场景
- 系统需要动态地在几种算法中选择一种,或者根据不同的条件选择不同的算法;
- 系统中有许多类似的行为,但是具体实现上有所不同,可以使用策略模式将这些行为抽象出来,并定义一个接口或抽象类,然后由具体的实现类来实现这个接口或抽象类;
- 一些算法使用了相同的数据,但是实现上有所不同,可以使用策略模式来避免代码重复和代码膨胀,节省代码维护成本。
相关文章:
策略模式【行为模式C++】
1.概述 策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。 策略模式通常应用于需要多种算法进行操作的场景,如排序、搜索、数据压缩等。在这些情况下&#x…...
php中session相关知识(目前了解部分)
#记录学习知识 一.ini_set() 在PHP中,ini_set() 函数用于在脚本运行时设置指定的配置选项的值。这些配置选项可以是PHP的核心设置,例如文件上传的最大大小、脚本的最大执行时间、错误报告级别等。使用 ini_set() 可以临时改变PHP.ini文件中的设置&am…...
从零实现诗词GPT大模型:GPT是怎么生成内容的?
专栏规划: https://qibin.blog.csdn.net/article/details/137728228 再开始编写GPT之前,我们得对GPT是怎么生成内容的有一个大致的了解。目前的神经网络我们大多都可以看成是一个黑盒,即我们把数据输送给网络后,网络给我我们输出,我们可以不用关心这个黑盒里到底是怎么实现…...
8路HDMI+8路AV高清视频流媒体编码器JR-3218HD
产品简介: JR-3218HD高清音视频编码产品支持8路高清HDMI音视频采集功能,8路AV视频采集功能,8路3.5MM独独立音频接口采集功能。编码输出双码流H.264格式,音频MP3/AAC格式。编码码率可调,画面质量可控制。支持HTTP/RTSP…...
LangChain入门:14.LLMChain:最简单的链的使用
摘要 本文将介绍LangChain库中LLMChain工具的使用方法。LLMChain将提示模板、语言模型(LLM)和输出解析器整合在一起,形成一个连贯的处理链,简化了与语言模型的交互过程。我们将探讨LLMChain的技术特点、应用场景以及它解决的问题…...
深入理解k8s kube-proxy
1、概述 我觉得只要大家知道kube-proxy是用来配置网络规则的而不是转发流量的,真正的流量由iptables/ipvs来转发就可以了。 网络是k8s的一个关键部分。理解k8s中网络组件如何工作可以帮助更好的设计和配置我们的应用。 kube-proxy就是K8s网络的核心组件。它把我们…...
Spark-机器学习(1)什么是机器学习与MLlib算法库的认识
从这一系列开始,我会带着大家一起了解我们的机器学习,了解我们spark机器学习中的MLIib算法库,知道它大概的模型,熟悉并认识它。同时,本篇文章为个人spark免费专栏的系列文章,有兴趣的可以收藏关注一下&…...
java的正则表达式校验,包含了中国几乎所有运营商手机号码的校验格式
时间2024年4月14日22:25:00 代码 String PHONE_REGEX "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";解释 这个Java代码段定义了一个常量 PHONE_REGEX,它包含了一个正则表达式,用于匹配中国大陆的手机号码。下面是对这…...
C#简单工厂模式的实现
using System.Diagnostics.Metrics; using System.Runtime.InteropServices; using static 手写工厂模式.Program;namespace 手写工厂模式 {internal class Program{public interface eats {void eat();}//定义了一个接口public class rice : eats{public void eat() {Console.…...
.NET 设计模式—观察者模式(Observer Pattern)
简介 在.NET中,观察者模式是一种设计模式,它允许对象之间进行一对多的依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这种模式在事件驱动的设计中非常常见。 在.NET中实现观察者模式,通常涉…...
EasyUI Jquery 学习笔记 ——DataGrid(数据网格)与 Tree(树)详细版
1. DataGrid(数据网格)与 Tree(树) 1.1 Datagrid 数据网格 扩展自 $.fn.panel.defaults。通过 $.fn.datagrid.defaults 重写默认的 defaults。 数据网格(datagrid)以表格格式显示数据,并为选择、排序、分组和编辑数据提供了丰富的支持。数据网格(datagrid)的设计目…...
JAVA发票验真接口、票据ocr、数电票在线查验真伪
发票验真接口,,实时联网核验发票真伪,查验一致返回全票面信息,支持查验增值税发票管理系统开具的发票,支持批量核验发票,翔云发票查验送发票识别,助您摆脱手动输入繁琐,提升工作效率。 发票查验接口适用于银行、金融、代理记账等发票管理数量…...
el-date-picker调用回车事件
elementui的el-date-picker想要调用回车事件: <el-date-pickerv-model"state.date"type"date"value-format"YYYY-MM-DD HH:mm:ss"placeholder"选择日期"clearablekeydown.enter"handleDown"></el-date-…...
js学习总结
这里写目录标题 前情提要JavaScript书写位置1. 内部javaScript (不常用)2. 外部javaScript (常用)3.内联javaScript (常用) js中的输入和输出输出语法1. document.write()2. alert()3. console.log() 输入语法prompt() 前情提要 1. 在javaScript中的 分号 是可以省略的JavaScr…...
MES实施优势有哪些?MES制造执行系统的主要内容
各个行业之间也开始进入到了激烈的竞争当中,很多企业为了能够有效提升企业竞争力,都会通过提升自身实力的方式来提升竞争力。一些制造业也会在经营过程当中使用到MES系统,那么,mes系统的优势有哪些呢? 1、优化企业现场…...
ChatGPT 和 Elasticsearch:使用 Elastic 数据创建自定义 GPT
作者:Sandra Gonzales ChatGPT Plus 订阅者现在有机会创建他们自己的定制版 ChatGPT,称为 GPT,这替代了之前博客文章中讨论的插件。基于本系列的第一部分的基础 —— 我们深入探讨了在 Elastic Cloud 中设置 Elasticsearch 数据和创建向量嵌…...
废品回收 小程序+APP
用户实名认证、回收员实名认证、后台审核、会员管理、回收员管理、订单管理、提现管理、地图、档案管理。 支持,安卓APP、苹果APP、小程序 流程: 一、用户端下单,地图选择上门位置、填写具体位置、废品名称、预估重量、选择是企业废旧、家…...
下载好了annaconda,但是在创建一个新的Conda虚拟环境报错
文章目录 问题描述:解决方案1.生成一个配置文件 问题总结 问题描述: ProxyError(MaxRetryError(“HTTPSConnectionPool(host‘repo.anaconda.com’, port443): Max retries exceeded with url: /pkgs/pro/win-64/repodata.json.bz2 (Caused by ProxyErr…...
如何安装MacOS的虚拟机?mac安装虚拟机的步骤 虚拟机安装MacOS VMware Fusion和Parallels Desktop19
要在Mac上运行MacOS的虚拟机,常用的方法是使用虚拟化软件如VMware Fusion或Parallels Desktop。 以下是安装MacOS的虚拟机的主要步骤: 1. 检查系统要求:确定您的Mac硬件和操作系统满足安装要求。您需要一台具备足够性能的Mac,并…...
Flutter 中 AutomaticKeepAliveClientMixin 的介绍及使用
在 Flutter 中,当你在一个页面中滑动列表或者进行其他一些操作时,如果你返回到该页面,可能会发现之前的状态已经丢失了。这在某些情况下可能是不可取的,特别是当你想要保留之前的状态,而不是每次都重新加载页面时。 为…...
注意力机制篇 | YOLOv8改进之清华开源ACmix:自注意力和CNN的融合 | 性能速度全面提升
前言:Hello大家好,我是小哥谈。混合模型ACmix将自注意力机制和卷积神经网络进行整合,使其同时具有自注意力机制和卷积神经网络的优点。这是清华大学、华为和北京人工智能研究院共同发布在2022年CVPR中的论文。ACmix结合了自注意力机制和卷积神经网络的优势,以提高模型的性能…...
Go语言支持重载吗?如何实现重写?
Go语言不支持传统意义上的函数和方法重载。在Go语言中,函数名或方法名不能相同但参数列表不同,因为这会导致编译错误。 然而,可以通过方法重写(override)来实现类似的功能。方法重写是指在子类中定义一个与父类同名的…...
Spring中基于事件监听驱动 和 线程池的异步任务
文章目录 事件监听驱动 与 异步事件源ApplicationContextAware接口 发布事件事件实体监听事件实现异步注入綫程池 事件驱动机制,与MQ消息队列比较 事件监听驱动 与 异步 事件监听驱动优点:解耦,将 事件和业务进行解耦,通过Asyc注解…...
C++ 优先级队列用法详解与模拟实现
文章目录 C 优先级队列用法与模拟实现介绍用法头文件1.创建优先级队列priority_queue 2. 插入元素push 3. 删除元素pop 访问顶部元素top 检查优先级队列的大小size 检查优先级队列是否为空empty 模拟实现 C 优先级队列用法与模拟实现 介绍 优先级队列(Priority Qu…...
Linux进阶之旅:深入探索Linux的高级功能
文章目录 Linux进阶之旅:深入探索Linux的高级功能1. Shell脚本编程2. 进程管理3. 网络管理4. 文本处理5. 系统监控6. 总结 Linux进阶之旅:深入探索Linux的高级功能 在上一篇博客中,我们对Linux操作系统进行了入门级的介绍,包括Linux的特点、发行版、安装方法以及基本使用。接下…...
【Java】内存可见性问题是什么?
文章目录 内存模型内存可见性解决方案volatile 内存模型 什么是JAVA 内存模型? Java Memory Model (JAVA 内存模型)是描述线程之间如何通过内存(memory)来进行交互。 具体说来, JVM中存在一个主存区(Main Memory或Java Heap Mem…...
Guava里一些比较常用的工具
随着java版本的更新提供了越来越多的语法和工具来简化日常开发,但是我们一般用的比较早的版本所以体验不到。这时就用到了guava这个包。guava提供了很多方便的工具方法,solar框架就依赖了guava的16.0.1版本,这里稍微介绍下。 一、集合工具类…...
在windows系统中【.gz.tar】和【.whl】文件分别应该怎么下载到conda的某个虚拟环境中
在 Windows 系统中,你可以按照以下步骤将 .gz.tar 和 .whl 文件下载到 Conda 的某个虚拟环境中: 激活虚拟环境:打开 Anaconda Prompt 或者命令行窗口,使用以下命令激活你想要安装文件的虚拟环境: conda activate <虚…...
Rust - 数据类型
Rust 是静态编译语言,在编译时必须知道所有变量的类型。 基于使用的值,编译器通常能推断出它的具体类型,但如果可能的类型比较多,例如把String转换为整数的parse方法,就必须添加类型的标注,否则编译会报错…...
基于springboot实现洗衣店订单管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现洗衣店订单管理系统演示 摘要 随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个专门适应洗衣店业务新的交流形式的网站。本文介绍了洗衣店订单管理系统的开发全过程。通过分析企业对于洗衣店订单管理系统…...
无锡专业网站/做网站怎么优化
更新一下对应的PACK包...
网站结构分类/南京百度
Oracle基础练习题,采用Oracle数据库自带的表,适合初学者,其中包括了一些简单的查询,已经具有Oracle自身特点的单行函数的应用 本文使用的实例表结构与表的数据如下: emp员工表结构如下: Name Type …...
手机网站跟pc网站有什么不同/自媒体发稿
核心就一行指令sudo dd bs4m if2017-11-29-raspbian-stretch.img of/dev/rdisk4其中if参数为镜像文件,of参数为设备名称。但是烧写系统进sd卡前需要一个准备工作,其一是将sd卡抹掉格式化一下,然后卸载sd卡分区,最后将系统烧进指定…...
济南高端网站制作公司/企业培训有哪些方面
https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结一下转换的各种方法,包括JDK原生提供的,还有一些外部依赖提供的。1、InputStream转化为String1.1 JDK原生提供 方法…...
网站优化我自己可以做吗/google浏览器下载
一、MySQL官网下载MySQL5.7版本,我这里下载的是MySQL5.7.24。二、直接到D:phpStudyPHPTutorial目录下删除之前的MySQL版本,把下载好的MySQL5.7.24版本解压并修改为MySQL,然后在MySQL目录下新建my.ini文件并加入如下内容: [mysqld] port3306 b…...
怎样把域名和做的网站连接/十大室内设计网站
1.用annotation配置文件开发要明确告诉Spring框架我们是注解开发 版本spring-context 5.0.2 配置ApplicationContext.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xs…...