策略模式Strategy介绍与C++实现

news2024/11/18 11:17:10

目录

1、策略模式的提出:

2、策略模式定义:

3、策略模式总结:

4、需求描述:

5、普通实现

6、使用策略模式实现


1、策略模式的提出:

在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,会使对象变得异常的复杂,而且有时候支持不使用的类型算法也是一个性能开销(if中多个条件,switch中多个case)。

如果将算法跟对象的本身进行解耦,就可以解决上面的系统复杂和性能问题。

2、策略模式定义:

定义一系列算法,将它们一个一个都封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定结构)而变化(扩展--->子类化)。即:使用算法的客户程序流程不会随着算法需求的变化而变化,对于算法需求的变化可以在子类中进行适配。

3、策略模式总结:

(1)策略模式提供了条件判断语句if/switch的另一种实现方法,可以实现多个算法之间的解耦。注意:如果if、switch的条件类型是固定的,不会再扩展的话(eg:if的判断只有5种情况,不会再出现其他情况),则不使用策略类型。

(2)如果策略对象没有实例变量,那么上下文可以共享一个策略对象(单例模式),从而节省对象开销。

4、需求描述:

根据不同的水果类型和重量,输出对应水果的总价格。

5、普通实现

#include <iostream>

using namespace std;

enum class GoodsType
{
    EM_BANANA=0,
    EM_APPLE,
    EM_ORANGE,
    EM_GRAPE
};

/*
* 枚举类型优点:1、降低命名空间污染,访问方法:枚举类名::变量,eg:GoodsType::EM_BANANA
*             2、避免发生隐式转换,eg:int a = GoodsType::EM_APPLE;
*             3、可以前置声明,eg:enum class GoodsGType;
*/
class MyGoods
{
public:
    double GetPrice(const GoodsType& type,const double& kg)
    {
        double price = 0.0;
        if(GoodsType::EM_BANANA ==  type)
        {
            price = kg * 3.99;
        }else if(GoodsType::EM_APPLE ==  type)
        {
            price = kg * 7.99;
        }
        else if(GoodsType::EM_ORANGE ==  type)
        {
            price = kg * 8.99;
        }
        else if(GoodsType::EM_GRAPE ==  type)
        {
            price = kg * 18.99;
        }
        return price;
    };
};



int main()
{
    MyGoods obj;
    double kg = 18.00;
    GoodsType type = GoodsType::EM_GRAPE;
    std::cout << "price is " << obj.GetPrice(type,kg) << std::endl;
}

运行结果如下:

6、使用策略模式实现

#include <iostream>

using namespace std;

enum class GoodsType
{
    EM_BANANA=0,
    EM_APPLE,
    EM_ORANGE,
    EM_GRAPE
};

class AbsProduct
{
public:
    virtual double GetPrice(double& kg)=0;
    virtual ~AbsProduct(){};
};

class ProdutBanana:public AbsProduct
{
public:
    virtual double GetPrice(double &kg) override
    {
        return kg * 3.99;
    };
    virtual ~ProdutBanana(){};
};

class ProdutApple:public AbsProduct
{
public:
    virtual double GetPrice(double &kg) override
    {
        return kg * 7.99;
    };
    virtual ~ProdutApple(){};
};

class ProdutOrange:public AbsProduct
{
public:
    virtual double GetPrice(double &kg) override
    {
        return kg * 8.99;
    };
    virtual ~ProdutOrange(){};
};

class ProdutGrape:public AbsProduct
{
public:
    virtual double GetPrice(double &kg) override
    {
        return kg * 18.99;
    };
    virtual ~ProdutGrape(){};
};

class StrategyFactory
{
public:
    virtual AbsProduct* CreateProduct()=0;
    virtual ~StrategyFactory(){};
};

class FactoryBanana:public StrategyFactory
{
public:
    virtual AbsProduct * CreateProduct() override
    {
        return new ProdutBanana();
    }
};

class FactoryApple:public StrategyFactory
{
public:
    virtual AbsProduct * CreateProduct() override
    {
        return new ProdutApple();
    }
};

class FactoryOrange:public StrategyFactory
{
public:
    virtual AbsProduct * CreateProduct() override
    {
        return new ProdutOrange();
    }
};

class FactoryGrape:public StrategyFactory
{
public:
    virtual AbsProduct * CreateProduct() override
    {
        return new ProdutGrape();
    }
};

class MyGoods
{
private:
    AbsProduct* product = nullptr;

public:
    void SetProductType(StrategyFactory* pThis)
    {
        this->product = pThis->CreateProduct(); //产品类型对象的生成使用工厂方法模式实现
    }

    double GetPrice(double kg)
    {
        return product->GetPrice(kg);   //多态实现算法匹配
    }
    virtual ~MyGoods()
    {
        if(product != nullptr)
        {
            delete product;
            product = nullptr;
        }
    }
};

int main()
{
    double kg = 18.00;
    MyGoods obj;
    StrategyFactory *proGrape = new FactoryGrape();
    obj.SetProductType(proGrape);
    std::cout << "price is " << obj.GetPrice(kg) << std::endl;
    return 0;
}

运行结果如下:

 代码描述:使用策略模式,将获取的产品价格跟产品类型进行了解耦,MyGoods获取价格的实现步骤不会随着产品类型的变化而变化。

当具有新的产品类型时,只需要扩展定义新的产品和产品工厂类就可以适配新需求变化,这种代码具有可复用性和可扩展性。

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

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

相关文章

Ubuntu下 NVIDIA Container Runtime 安装与使用

NVIDIA Container Runtime官网 GitHub仓库&#xff1a;Docker 是开发人员采用最广泛的容器技术。借助 NVIDIA Container Runtime&#xff0c;开发人员只需在创建容器期间注册一个新的运行时&#xff0c;即可将 NVIDIA GPU 暴露给容器中的应用程序。用于 Docker 的 NVIDIA Conta…

自然语言处理:任务与应用

文章目录 一、基本任务1.词性标注Part-of-speech (POS) tagging2.命名实体识别Named Entity Recognition (NER)3.共指消解Coreference Resolution4.句法依赖解析Syntactic Dependency Parsing5.中文分词Chinese Word Segmentation 二、常见应用1.文本匹配2. 知识图谱3. 问答系统…

微服务中的负载均衡

如图 有三处需要负载均衡 这里主要讲内部的grpc调用的 负载均衡 图中3的地方 ① 集中式load balance ② 进程内load balance ③独立进程load balance 首选第二种方式

华为MateBook 16 2021款锐龙版R7(CREM-WFD9)(CREM-WFG9)原装出厂Win11系统工厂模式,恢复原厂系统

HUAWEI华为笔记本电脑&#xff0c;MateBook 16 2021款 锐龙版 R7(CREM-WFD9) (CREM-WFG9) 原厂Windows11系统&#xff0c;带F10恢复功能&#xff0c;原装OEM专用系统&#xff0c;恢复出厂状态 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、华为电脑管家等预装程序 …

Java启动项目时,控制台报端口被占用,解决办法

端口占用一般是现在有别的程序正在使用该端口 第一步可以先查出来是哪个程序在占用&#xff1a; netstat -aon | find "8113" //8113为被占用的端口号 此时的结果是这样的&#xff0c;查询出来的为占用此端口程序的PID&#xff08; 25472 &#xff09; 然后根据…

隐式迭代是什么意思?jQuery选择器隐式迭代

在使用jQuery 选择器获取元素后&#xff0c;如果不考虑获取到的元素数量&#xff0c;直接对元素进行操作&#xff0c;则在操作时会发生隐式迭代。隐式迭代是指&#xff0c;当要操作的元素实际有多个时&#xff0c;jQuery 会自动对所有的元素进行操作&#xff0c;示例代码如下。…

Centos 系统中使用 Firefix 播放视频 - VLC播放器的安装

问题&#xff1a; 出于刷视频的需要&#xff0c;需要使用虚拟机&#xff08;Centos7&#xff09;上的 Firefix 来播放视频&#xff0c;经确认安装 flash 的方式是不行的。事实上在 Firefix 播放视频仅需要安装 VLC 播放器就可以了&#xff0c;以下记录安装 VLC 视频播放器的过程…

Selenium教程__截图(16)

selenium截图有两种方式 截取全屏 get_screenshot_as_file(filename)&#xff1a;将截图转化成文件保存到本地&#xff0c;filename为保存的文件路径get_screenshot_as_base64()&#xff1a;将截图转化成base64get_screenshot_as_png()&#xff1a;将截图转化成png 截取指定元…

Java学习记录之struts2(一)

1 struts入门 1.1 介绍  框架&#xff1a;就是半成品&#xff0c;框架已经完成一些通用功能。只需要实现与业务有关功能。  版本&#xff1a;struts-2.3.15.3-all 1.2 核心功能 1.3 目录结构  apps / struts2-blank.war 最简答环境  apps / struts2-showcase.war 常…

【Linux】MySQL 主从复制与读写分离

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 主从复制与读写分离 MySQL 主从复制与读写分离1、什么是读写分离2、为什么要读写分离3、什么时候要读写分离4、主从复制与读写分离5、mysql支持的复制类型6、主从复制的…

Unity Android启动子进程加载其他SDK

1、导出untiy 安卓工程 添加MyService 2、 在子进程内加载SDK部分

【C#】错误 14 “GenerateResource”任务意外失败。

问题描述 Microsoft Visual Studio Ultimate 2013 12.0.21005.1 错误 14 “GenerateResource”任务意外失败。 System.Runtime.InteropServices.ExternalException (0x80004005): GDI 中发生一般性错误。在 System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder,…

开车适合佩戴哪种蓝牙耳机,分享几款骨传导耳机的使用体验

骨传导耳机从发布到现在有了几年的时间&#xff0c;也有很多人开始了解&#xff0c;但真正去选购的人还是很少&#xff0c;如果你没有使用过骨传导耳机&#xff0c;在选购时会很迷茫。作为一个骨传导耳机的重度使用者&#xff0c;下面就给大家分享一下我的体验感受以及选购建议…

大模型微调实践遗留问题1

Lora 和 AdaLora的区别和联系&#xff1f; P-tuning和Prompt tuning的区别和联系&#xff1f; P-Tuning&#xff0c;仅对大模型的Embedding加入新的参数。 P-Tuning-V2&#xff0c;将大模型的Embedding和每一层前都加上新的参数。 Prompt Tuning 方式可以看做是 Prefix Tuni…

自学黑客(网络安全),一般人我劝你还是算了吧(自学网络安全学习路线--第十二章 无线网络安全下)【建议收藏】

文章目录 一、自学网络安全学习的误区和陷阱二、学习网络安全的一些前期准备三、自学网络安全学习路线一、无线局域网安全性分析1、Wi-Fi网络安全2、WEP存在如下弱点&#xff1a; 二、移动通信网安全防护1、3G安全体系趋于透明化2、考虑采用公钥密码体系3、考虑新密码技术的应用…

kafka入门,生产者自定义分区(六)

1、实现Partitioner接口 package com.longer.producer;import org.apache.kafka.clients.producer.Partitioner; import org.apache.kafka.common.Cluster;import java.util.Map;/*** 实现接口Partitioner* 实现3个方法&#xff1a;partition&#xff0c;close,configure* 编写…

EasyCVR级联后上级在线,请求播放显示端口不可达是什么原因?

EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&#xff0c;比如&#xff1a;视…

TestNG单元测试报错Software caused connection abort: socket write error

在用TestNG进行单元测试时&#xff0c;总出现如下错误&#xff1a;Software caused connection abort: socket write error 解决方法&#xff1a; 报错前我使用的eclipse testng插件版本为6.11&#xff0c;对插件版本降为6.8后此问题解决。&#xff08;先卸载已装testng插件&…

通过精益价值流探索研发效能提升实践

研发效能八大损耗 采用精益价值流进行分析&#xff0c;研发过程存在以下典型的八大损耗 01 缺陷修复 因上游质量问题后移而引发的工作返工&#xff0c;一般会占用新功能的时间投入&#xff0c;如果经常反复回流&#xff0c;将严重影响团队的需求交付吞吐量 02 工作等待 上游…

Postman接口测试工具使用教程【基础版】

postmanpostman是一款支持http协议的接口调试与测试工具&#xff0c;其主要特点就是功能强大&#xff0c;使用简单且易用性好 。无论是开发人员进行接口调试&#xff0c;还是测试人员做接口测试&#xff0c;postman都是我们的首选工具之一 。那么接下来就介绍下postman到底有哪…