C++11 设计模式7 策略模式 ,Strategy

策略模式的概念:

策略模式(Strategy Pattern)是 C++ 中常用的一种行为设计模式,它能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。

在策略模式中,需要创建表示各种策略的对象和一个行为随着策略对象改变而改变的 Context 对象。策略对象更改 Context 对象的执行算法。

在策略模式中,通常包括以下几个角色:

(1)策略接口(Strategy Interface): 定义了一个策略的公共接口,所有具体的策略类都需要实现这个接口。这个接口声明了策略对象将执行的操作。

(2)具体策略类(Concrete Strategy Classes): 实现了策略接口,提供了具体的算法或行为。每个具体策略类都封装了实现特定行为或算法的代码。

(3)上下文(Context): 维护一个指向策略对象的引用,并定义一个接口来让策略对象执行其算法。上下文类并不知道具体的策略类,它只知道策略接口。这样,上下文可以将请求转发给当前关联的策略对象来执行。

2 策略模式的实现步骤
在 C++ 实现策略模式的实现步骤如下:

(1)定义策略接口:
首先,需要定义一个策略接口。这个接口通常是一个纯虚类,声明了一组公共的、需要由具体策略类来实现的方法。这些方法是策略对象将执行的行为的抽象描述。

(2)实现具体策略类:
接下来,创建实现策略接口的具体策略类。每个具体策略类都包含了实现特定算法或行为的代码。这些类继承了策略接口,并实现了接口中声明的所有方法。

(3)创建上下文类:
上下文类负责维护对策略对象的引用,并定义了一个接口,以便客户端代码可以通过这个接口来执行策略对象的方法。上下文类通常包含一个指向策略接口的指针或引用,并通过这个指针或引用来调用策略方法。上下文类本身并不关心具体使用了哪个策略,它只关心策略接口。

(4)在上下文中设置策略对象:
在客户端代码中,创建具体策略类的对象,并将其传递给上下文对象。上下文对象使用这个策略对象来执行相应的算法或行为。客户端代码可以通过调用上下文类的方法来间接调用策略对象的方法。

(5)执行策略:
客户端代码通过调用上下文类的执行方法(例如 executeStrategy()),来触发策略的执行。上下文类将调用当前设置的策略对象的方法,实现相应的算法或行为。

(6)更改策略:
如果需要改变行为,客户端代码可以创建另一个策略对象,并将其设置为上下文对象的新策略。这样,上下文对象在执行策略时会使用新的算法或行为。

通过这些步骤,策略模式允许在运行时动态地改变对象的行为,提高了代码的灵活性和可维护性。它通过将算法和行为封装在独立的策略类中,实现了算法与使用算法的客户端代码之间的解耦。这样,客户端代码只需关注于如何使用策略,而不需要关心策略的具体实现。

#include <iostream>  
#include <memory>// 步骤1: 定义策略接口  
class Strategy {
public:virtual ~Strategy() {}virtual void execute() = 0;
};// 步骤2: 实现具体策略类  
class ConcreteStrategyA : public Strategy {
public:void execute() override {std::cout << "Executing strategy A" << std::endl;}
};class ConcreteStrategyB : public Strategy {
public:void execute() override {std::cout << "Executing strategy B" << std::endl;}
};// 步骤3: 创建上下文类  
class Context {
public:// 通过构造函数设置策略  Context(std::unique_ptr<Strategy> strategy) : strategy(std::move(strategy)) {}// 执行策略  void executeStrategy() {if (strategy) {strategy->execute();}else {std::cout << "No strategy is set." << std::endl;}}// 更改策略  void setStrategy(std::unique_ptr<Strategy> newStrategy) {strategy = std::move(newStrategy);}private:std::unique_ptr<Strategy> strategy; // 使用unique_ptr管理策略对象的生命周期  
};// 步骤4-6: 在客户端代码中设置和执行策略  
int main() 
{// 创建具体策略对象并使用unique_ptr管理  auto strategyA = std::make_unique<ConcreteStrategyA>();auto strategyB = std::make_unique<ConcreteStrategyB>();// 创建上下文对象并设置初始策略  Context context(std::move(strategyA));context.executeStrategy(); // 输出:Executing strategy A  // 更改策略  context.setStrategy(std::move(strategyB));context.executeStrategy(); // 输出:Executing strategy B  // 此时strategyA和strategyB已经被unique_ptr自动释放  return 0;
}

假设公司是有一个算税法的函数。

不同的国家有不同的算税法的逻辑。

刚开始有三个国家,china,us,japan

你可能这么写:

//不同的国家有不同的算税法的逻辑。各个国家会根据不同销售额计算税率
//
//刚开始有三个国家,china,us,japan
//
//你可能这么写:#include <iostream>
using namespace std;enum TaxCountry {china_tax,us_tax,japan_tax
};//销售额类
class SaleOrder {
public:SaleOrder(int oneyeassalenum) {onesalemoney = oneyeassalenum;}int calculateTax() {if (taxcoutury== china_tax) {//如果是中国return onesalemoney / 3;}else if (taxcoutury == us_tax) {return onesalemoney / 2;}else if (taxcoutury == japan_tax) {return onesalemoney / 4;}}void setTaxCountry(TaxCountry _taxcoutury) {taxcoutury = _taxcoutury;}private:TaxCountry taxcoutury;int onesalemoney;
};int main()
{std::cout << "Hello World!\n";SaleOrder so(100);so.setTaxCountry(TaxCountry::china_tax);int result = so.calculateTax();cout << "result = " << result << endl;
}

但是随着业务的扩展,我们可能还要做德国的,法国的,印度的

那么这就要改动代码了,不符合开闭原则。

使用 策略模式改动

// 005策略模式.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//假设我们是做
//不同的国家有不同的算税法的逻辑。各个国家会根据不同销售额计算税率
//
//刚开始有三个国家,china,us,japan
//
//你可能这么写:#include <iostream>
using namespace std;enum TaxCountry {china_tax,us_tax,japan_tax
};//销售额类
class SaleOrder {
public:SaleOrder(int oneyeassalenum) {onesalemoney = oneyeassalenum;}int calculateTax() {if (taxcoutury== china_tax) {//如果是中国return onesalemoney / 3;}else if (taxcoutury == us_tax) {return onesalemoney / 2;}else if (taxcoutury == japan_tax) {return onesalemoney / 4;}}void setTaxCountry(TaxCountry _taxcoutury) {taxcoutury = _taxcoutury;}private:TaxCountry taxcoutury;int onesalemoney;
};int main005()
{std::cout << "Hello World!\n";SaleOrder so(100);so.setTaxCountry(TaxCountry::china_tax);int result = so.calculateTax();cout << "result = " << result << endl;return 0;
}// 策略基类
class TaxStrategy {
public:virtual int calculateTax(int onesalemoney) = 0;virtual ~TaxStrategy() {}
};// china策略实现
class ChinaTaxStrategy : public TaxStrategy {
public:int calculateTax(int onesalemoney) override {cout << "china calculateTax" << endl;return onesalemoney / 3;}
};// us 策略实现
class USTaxStrategy : public TaxStrategy {
public:int calculateTax(int onesalemoney) override {cout << "us calculateTax" << endl;return onesalemoney / 2;}
};//japan 策略实现
class JapanTaxStrategy : public TaxStrategy {
public:int calculateTax(int onesalemoney) override {cout << "japan calculateTax" << endl;return onesalemoney / 4;}
};//法国策略实现
class FranceTaxStrategy : public TaxStrategy {
public:int calculateTax(int onesalemoney) override {cout << "france calculateTax" << endl;return onesalemoney / 5;}
};// 上下文类
class Context {
private:TaxStrategy* strategy;int oneyearmoney;
public:Context(TaxStrategy* s, int money) : strategy(s), oneyearmoney(money){}int ContextInterface() {return strategy->calculateTax(oneyearmoney);}
};int main() {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口TaxStrategy * ts = NULL;ts = new ChinaTaxStrategy();int result  = ts->calculateTax(1000);cout << "result = " << result << endl;delete ts;//	也可以通过创建一个上下文来处理// 创建具体策略对象TaxStrategy* strategyA = new ChinaTaxStrategy();TaxStrategy* strategyB = new USTaxStrategy();// 设置策略并调用Context* contextChina = new Context(strategyA,10000);result = contextChina->ContextInterface();cout << "result = " << result << endl;Context* contextUS = new Context(strategyB,200000);result = contextUS->ContextInterface();cout << "result = " << result << endl;delete contextUS;delete contextChina;delete strategyB;delete strategyA;return 0;
}

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

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

相关文章

每日一题 礼物的最大价值

题目描述 礼物的最大价值_牛客题霸_牛客网 解题思路 这是一个典型的动态规划问题。我们可以使用一个二维数组 dp[][] 来存储到达每个格子时可以获得的最大价值。状态转移方程为 dp[i][j] max(dp[i-1][j], dp[i][j-1]) grid[i][j]&#xff0c;表示到达当前格子的最大价值是从…

Windows PC上从零开始部署ChatGML-6B-int4量化模型

引言 ChatGLM-6B是清华大学知识工程和数据挖掘小组&#xff08;Knowledge Engineering Group (KEG) & Data Mining at Tsinghua University&#xff09;发布的一个开源的对话机器人。6B表示这是ChatGLM模型的60亿参数的小规模版本&#xff0c;约60亿参数。 ChatGML-6B-in…

面试 Java 基础八股文十问十答第三十一期

面试 Java 基础八股文十问十答第三十一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;TreeMap 有了解过吗…

knife4j-openapi3 使用笔记

knife4j官方文档&#xff1a;https://doc.xiaominfo.com/docs/quick-start/start-knife4j-version 增强模式文档&#xff1a;https://doc.xiaominfo.com/docs/features/enhance 1.用法 &#xff08;1&#xff09;控制层 Tag(name “用户信息管理”) Tag(name "用户信…

代码随想录第四十六天|单词拆分

题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09;

STM32F4xx开发学习_SysTick

SysTick系统定时器 SysTick属于CM4内核外设&#xff0c;有关寄存器的定义和部分库函数都在core_cm4.h这个头文件中实现&#xff0c;可用于操作系统&#xff0c;提供必要的时钟节拍 SysTick简介 SysTick是一个 24 位向下定时器&#xff0c;属于CM4内核中的一个外设&#xff0c;…

无卤素产品是什么?有什么作用?

无卤素产品&#xff0c;即在生产过程中完全不使用卤素元素——氟、氯、溴、碘等——的产品。 卤素元素&#xff0c;虽然在电子设备、材料等领域应用广泛&#xff0c;却也可能潜藏危害。其阻燃剂&#xff0c;一旦在产品生命周期结束后释放&#xff0c;将对土壤和水体造成污染&a…

Python-100-Days: Day11 Files and Exception

1.读取csv文件 读取文本文件时&#xff0c;需要在使用open函数时指定好带路径的文件名&#xff08;可以使用相对路径或绝对路径&#xff09;并将文件模式设置为r&#xff08;如果不指定&#xff0c;默认值也是r&#xff09;&#xff0c;然后通过encoding参数指定编码&#xf…

MyBatis入门例子

1、建立与数据库对应的POJO类 2、建立mybatis的配置文件 修改后如下&#xff1a; 3、创建POJO对象和Mysql数据的表之间的映射配置 4、建一个测试方法 实现从数据库中取数一条数据&#xff0c;封装成User对象返回 注意点&#xff1a; 这点&#xff0c;大家应该不陌生了&#x…

照片太大上传不了怎么缩小?教你几招压缩图片

在日常的工作和学习中&#xff0c;我们经常要用到一些图片文件&#xff0c;储存的图片多了之后&#xff0c;会对我们的电脑或者手机有影响&#xff0c;需要我们使用图片处理工具来压缩图片大小&#xff0c;那么有没有比较简单的图片压缩的方法呢&#xff1f;试试今天分享的几个…

【管理咨询宝藏94】某国际咨询公司供应链财务数字化转型方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏94】某国际咨询公司供应链&财务数字化转型方案 【格式】PDF版本 【关键词】国际咨询公司、制造型企业转型、数字化转型 【核心观点】 - 172…

VS2019编译 Qt5.15.12 和 Qt6.5.3

参考链接: Windows平台编译Qt5.15.12、6.5.3过程记录_qt 5.15 版本-CSDN博客 软件环境准备 Windows&#xff1a;MSDN系统库&#xff0d;致力于原版windows生态服务 Visual Studio 2022&#xff1a;下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux cmake&am…

synchronized与volatile关键字

1.synchronized的特性 1.1互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到 同一个对象 synchronized 就会阻塞等待. 进入 synchronized 修饰的代码块, 相当于 加锁 退出 synchronized 修饰的代码块, 相当于 解锁 syn…

3行代码,实现一个取色器

前言 今天发现了一个很好玩的 API ——EyeDropper。 EyeDropper API 提供了一种创建拾色器工具的机制。使用该工具,用户可以从屏幕上取样颜色,包括浏览器窗口之外的区域。 这是 MDN 上对它的介绍,可以取包括浏览器窗口之外的区域。我们一起看看是怎么个事 什么是取色器 取…

611. 有效三角形的个数(双指针)

文章目录 前言一、题目解析二、代码原理1.暴力解法2.双指针优化 三、代码编写总结 前言 在本篇文章中&#xff0c;我们将会带着大家解决一下611. 有效三角形的个数这道题目&#xff0c;本道题木将会用双指针的方法解决。 一、题目解析 给定一个包含非负整数的数组 nums &…

关于Oracle 23ai 你要知道的几件事情

1.版本生命周期 23ai发布后的Oracle版本生命周期图&#xff0c;可以看到23ai是长期支持版本可以到2032年。 引申 Oracle版本分为两类 Innovation Release--创新版本&#xff0c;一般提供至少两年技术支持 Long Term Release --长期支持版本&#xff0c;一般提供5年premier和…

酸奶(科普)

酸奶&#xff08;yogurt&#xff09;是一种酸甜口味的牛奶饮品&#xff0c;是以牛奶为原料&#xff0c;经过巴氏杀菌后再向牛奶中添加有益菌&#xff08;发酵剂&#xff09;&#xff0c;经发酵后&#xff0c;再冷却灌装的一种牛奶制品。市场上酸奶制品多以凝固型、搅拌型和添加…

开启智能新纪元:揭秘现代化仓储物流园区的数字孪生魅力

在数字化浪潮的推动下&#xff0c;物流行业正迎来前所未有的变革&#xff0c;现代化仓储物流园区数字孪生系统正以其独特的魅力引领着物流行业迈向更加智能、高效的新时代。 图源&#xff1a;山海鲸可视化 一、数字孪生&#xff1a;物流行业的“虚拟镜像” 数字孪生技术作为工…

C++细节,可能存在的隐患,面试题03

文章目录 11. C编译过程12. const vs #define12.1. 全局const vs 局部const 13. C内存分区14. C变量作用域14.1. 常量 vs 全局变量 vs 静态变量 15. C类型转换16. 函数指针17. 悬空指针 vs 野指针18. 为什么使用空指针&#xff0c;建议使用nullptr而不是NULL&#xff1f; 11. C…

JAVA面试常见面试问题01

1、队列系列 1.1、选型 ActiveMq ⼩规模场景&#xff0c;有较低概率丢失消息&#xff0c;官方社区维护少 RabbitMq ⼩规模场景&#xff0c;吞吐量⽐较低&#xff0c;消息积累会严重影响性能 RocketMQ ⼩规模场景&#xff0c;官⽅⽂档和周边⽣态还不够成熟 Kafka 大规模场景…