当前位置: 首页 > news >正文

策略模式【行为模式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.应用场景

  • 系统需要动态地在几种算法中选择一种,或者根据不同的条件选择不同的算法;
  • 系统中有许多类似的行为,但是具体实现上有所不同,可以使用策略模式将这些行为抽象出来,并定义一个接口或抽象类,然后由具体的实现类来实现这个接口或抽象类;
  • 一些算法使用了相同的数据,但是实现上有所不同,可以使用策略模式来避免代码重复和代码膨胀,节省代码维护成本。
http://www.lryc.cn/news/338716.html

相关文章:

  • php中session相关知识(目前了解部分)
  • 从零实现诗词GPT大模型:GPT是怎么生成内容的?
  • 8路HDMI+8路AV高清视频流媒体编码器JR-3218HD
  • LangChain入门:14.LLMChain:最简单的链的使用
  • 深入理解k8s kube-proxy
  • Spark-机器学习(1)什么是机器学习与MLlib算法库的认识
  • java的正则表达式校验,包含了中国几乎所有运营商手机号码的校验格式
  • C#简单工厂模式的实现
  • .NET 设计模式—观察者模式(Observer Pattern)
  • EasyUI Jquery 学习笔记 ——DataGrid(数据网格)与 Tree(树)详细版
  • JAVA发票验真接口、票据ocr、数电票在线查验真伪
  • el-date-picker调用回车事件
  • js学习总结
  • MES实施优势有哪些?MES制造执行系统的主要内容
  • ChatGPT 和 Elasticsearch:使用 Elastic 数据创建自定义 GPT
  • 废品回收 小程序+APP
  • 下载好了annaconda,但是在创建一个新的Conda虚拟环境报错
  • 如何安装MacOS的虚拟机?mac安装虚拟机的步骤 虚拟机安装MacOS VMware Fusion和Parallels Desktop19
  • Flutter 中 AutomaticKeepAliveClientMixin 的介绍及使用
  • 注意力机制篇 | YOLOv8改进之清华开源ACmix:自注意力和CNN的融合 | 性能速度全面提升
  • Go语言支持重载吗?如何实现重写?
  • Spring中基于事件监听驱动 和 线程池的异步任务
  • C++ 优先级队列用法详解与模拟实现
  • Linux进阶之旅:深入探索Linux的高级功能
  • 【Java】内存可见性问题是什么?
  • Guava里一些比较常用的工具
  • 在windows系统中【.gz.tar】和【.whl】文件分别应该怎么下载到conda的某个虚拟环境中
  • Rust - 数据类型
  • 基于springboot实现洗衣店订单管理系统项目【项目源码+论文说明】计算机毕业设计
  • Java基础知识总结(53)