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

2024-05-01 05:36

本文主要是介绍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;
}

这篇关于C++11 设计模式7 策略模式 ,Strategy的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950826

相关文章

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

SpringBoot中的404错误:原因、影响及解决策略

《SpringBoot中的404错误:原因、影响及解决策略》本文详细介绍了SpringBoot中404错误的出现原因、影响以及处理策略,404错误常见于URL路径错误、控制器配置问题、静态资源配置错误... 目录Spring Boot中的404错误:原因、影响及处理策略404错误的出现原因1. URL路径错

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

使用C/C++调用libcurl调试消息的方式

《使用C/C++调用libcurl调试消息的方式》在使用C/C++调用libcurl进行HTTP请求时,有时我们需要查看请求的/应答消息的内容(包括请求头和请求体)以方便调试,libcurl提供了多种... 目录1. libcurl 调试工具简介2. 输出请求消息使用 CURLOPT_VERBOSE使用 C

C++实现获取本机MAC地址与IP地址

《C++实现获取本机MAC地址与IP地址》这篇文章主要为大家详细介绍了C++实现获取本机MAC地址与IP地址的两种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实际工作中,项目上常常需要获取本机的IP地址和MAC地址,在此使用两种方案获取1.MFC中获取IP和MAC地址获取