设计模式 策略模式(Strategy Pattern) C++表达

news2024/9/9 0:13:55

设计模式 策略模式(Strategy Pattern) C++表达

flyfish

策略模式(Strategy Pattern)是一种行为设计模式,它的核心思想是将一系列相关的算法或行为封装到独立的策略类中,并使得这些策略可以相互替换。主要用来定义一系列可互换的算法或行为。它允许在运行时选择和切换这些算法或行为,而不用修改使用它们的代码。

策略模式就像给的代码提供了一组不同的工具,每个工具都可以完成相似的工作(例如不同的送货方式)。可以根据需要随时更换这些工具,而不需要修改太多代码。

举个例子

想象一下,有一家快递公司,提供了不同的送货方式:比如通过快递车、无人机或自行车送货。每种送货方式都有不同的优缺点和适用场景。希望可以根据具体情况选择最合适的送货方式。

如何实现?

  1. 定义策略接口 :首先,定义一个公共接口,比如 DeliveryMethod,里面有一个 deliver 方法,所有具体的送货方式都要实现这个方法。
class DeliveryMethod {
public:
    virtual void deliver() const = 0; // 定义送货方法
    virtual ~DeliveryMethod() = default; // 虚析构函数
};
  1. 实现具体策略 :然后,为每种送货方式实现这个接口,比如 TruckDeliveryDroneDeliveryBikeDelivery
class TruckDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by truck." << std::endl;
    }
};

class DroneDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by drone." << std::endl;
    }
};

class BikeDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by bike." << std::endl;
    }
};
  1. 上下文类 :然后,有一个上下文类 DeliveryContext,它包含一个 DeliveryMethod 的对象,并在需要的时候调用 deliver 方法。这个上下文类可以动态地更换送货方式。
class DeliveryContext {
private:
    std::shared_ptr<DeliveryMethod> deliveryMethod; // 存储送货方法的指针
public:
    void setDeliveryMethod(std::shared_ptr<DeliveryMethod> method) {
        deliveryMethod = method;
    }

    void executeDelivery() const {
        if (deliveryMethod) {
            deliveryMethod->deliver();
        }
    }
};
  1. 使用策略模式 :在 main 函数中,可以创建不同的送货方式,并根据情况切换它们。
int main() {
    DeliveryContext context;

    // 设置并执行卡车送货
    context.setDeliveryMethod(std::make_shared<TruckDelivery>());
    context.executeDelivery();

    // 设置并执行无人机送货
    context.setDeliveryMethod(std::make_shared<DroneDelivery>());
    context.executeDelivery();

    // 设置并执行自行车送货
    context.setDeliveryMethod(std::make_shared<BikeDelivery>());
    context.executeDelivery();

    return 0;
}

完整示例:

#include <iostream>
#include <memory>

// 策略接口类
class DeliveryMethod {
public:
    virtual void deliver() const = 0; // 定义送货方法
    virtual ~DeliveryMethod() = default; // 虚析构函数
};

// 具体策略A类 - 卡车送货
class TruckDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by truck." << std::endl;
    }
};

// 具体策略B类 - 无人机送货
class DroneDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by drone." << std::endl;
    }
};

// 具体策略C类 - 自行车送货
class BikeDelivery : public DeliveryMethod {
public:
    void deliver() const override {
        std::cout << "Delivering by bike." << std::endl;
    }
};

// 上下文类
class DeliveryContext {
private:
    std::shared_ptr<DeliveryMethod> deliveryMethod; // 存储送货方法的指针

public:
    // 设置策略方法
    void setDeliveryMethod(std::shared_ptr<DeliveryMethod> method) {
        deliveryMethod = method;
    }

    // 执行策略方法
    void executeDelivery() const {
        if (deliveryMethod) {
            deliveryMethod->deliver();
        }
    }
};

int main() {
    DeliveryContext context; // 创建上下文对象

    // 设置并执行卡车送货
    context.setDeliveryMethod(std::make_shared<TruckDelivery>());
    context.executeDelivery();

    // 设置并执行无人机送货
    context.setDeliveryMethod(std::make_shared<DroneDelivery>());
    context.executeDelivery();

    // 设置并执行自行车送货
    context.setDeliveryMethod(std::make_shared<BikeDelivery>());
    context.executeDelivery();

    return 0;
}

策略模式还是这样写

  1. 使用 shared_ptr :允许多个上下文对象共享同一个策略对象,节省内存。
  2. 策略工厂和注册机制 :使用 StrategyFactory 类进行策略的注册和创建,支持动态添加新策略,并避免重复创建策略对象。
  3. 简化策略设置 :通过策略名称字符串来设置策略。
#include <iostream>
#include <memory>
#include <unordered_map>
#include <functional>

// 策略接口类
class Strategy {
public:
    virtual ~Strategy() = default; // 虚析构函数,确保派生类对象可以被正确销毁
    virtual void execute() const = 0; // 纯虚函数,定义了算法的接口
};

// 具体策略A类
class ConcreteStrategyA : public Strategy {
public:
    void execute() const override {
        std::cout << "Strategy A executed." << std::endl;
    }
};

// 具体策略B类
class ConcreteStrategyB : public Strategy {
public:
    void execute() const override {
        std::cout << "Strategy B executed." << std::endl;
    }
};

// 策略工厂类
class StrategyFactory {
public:
    using CreateStrategyFn = std::function<std::shared_ptr<Strategy>()>;

    static StrategyFactory& instance() {
        static StrategyFactory factory;
        return factory;
    }

    void registerStrategy(const std::string& name, CreateStrategyFn createFn) {
        strategyMap_[name] = createFn;
    }

    std::shared_ptr<Strategy> getStrategy(const std::string& name) {
        auto it = strategyMap_.find(name);
        if (it != strategyMap_.end()) {
            return it->second();
        }
        return nullptr;
    }

private:
    std::unordered_map<std::string, CreateStrategyFn> strategyMap_;
};

// 上下文类
class Context {
private:
    std::shared_ptr<Strategy> strategy_; // 存储策略对象的智能指针

public:
    // 设置策略方法
    void setStrategy(const std::string& strategyName) {
        strategy_ = StrategyFactory::instance().getStrategy(strategyName);
    }

    // 执行策略方法
    void executeStrategy() const {
        if (strategy_) {
            strategy_->execute(); // 调用当前策略的执行方法
        }
    }
};

int main() {
    // 注册策略
    StrategyFactory::instance().registerStrategy("A", []() { return std::make_shared<ConcreteStrategyA>(); });
    StrategyFactory::instance().registerStrategy("B", []() { return std::make_shared<ConcreteStrategyB>(); });

    Context context; // 创建上下文对象

    // 设置并执行策略A
    context.setStrategy("A");
    context.executeStrategy();

    // 设置并执行策略B
    context.setStrategy("B");
    context.executeStrategy();

    return 0;
}

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

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

相关文章

Qt Designer,仿作一个ui界面的练习(二):部件内容的填充

有了完成了布局的基本框架设计之后&#xff0c;对各个部件逐步完成内容的填充。 一、还是从顶边栏开始&#xff1a; 1、在顶边栏的topLogo里面拖入一个QLabel&#xff08;标签&#xff09;&#xff0c;命名为logoImage&#xff0c;删除标签的文字。 2、右键点击topLogo&#x…

[Linux安全运维] LAMP 环境搭建保姆级教学(Apache + MySQL + PHP) ~~

LAMP LAMP 是一种网站技术&#xff0c;可以实现动态的网站页面部署。 1. LAMP概述 1 .1构成 Linux: 简介: Linux 是一种开源的操作系统&#xff0c;以其稳定性和安全性而著称。在 LAMP 堆栈中&#xff0c;它作为服务器操作系统运行。作用: 为应用程序提供一个稳定、安全的运…

为了方便写CURD代码,我在UTools写了个插件SqlConvert来生成代码!

-1. 前言 为了方便摸鱼&#xff0c;我之前写过一个通过sql生成代码的工具&#xff0c;但是服务器到期了&#xff0c;也就懒得重新部署了。 技术框架是 SpringBoot MybatisPlus Velocity Vue ElementUI Sql-ParseeSql-Parser-ui 0. Utools应用安装 官网地址: https://u.too…

达梦数据库归档介绍

一、什么是归档 数据库归档是一种数据管理策略&#xff0c;它涉及将旧的、不经常访问的数据移动到一个单独的存储设备&#xff0c;以便在需要时可以检索&#xff0c;同时保持数据库的性能和效率。 归档的主要目标是为了释放数据库中的空间&#xff0c;以便更有效地利用高性能…

如何用PostMan按照规律进行循环访问接口

①设置动态变量 步骤一: 设置环境变量 1. 创建环境变量集合 在 Postman 左上角选择 "环境"&#xff0c;然后点击 "添加" 来创建一个新的环境变量集合。给它起一个名称&#xff0c;比如 "uploadDemo". 2. 添加初始变量 在新创建的环境变量集…

校车购票小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;我的乘车信息管理&#xff0c;车辆信息管理&#xff0c;座位管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;车辆信息&#xff0c;我的 开发系统…

electron 主进程和渲染进程

最近在整理electron 相关的项目问题&#xff0c;对自己来说也是温故知新&#xff0c;也希望能对小伙伴们有所帮助&#xff0c;大家共同努力共同进步。加油&#xff01;&#xff01;&#xff01;&#xff01; 虽然最近一年前端大环境不好&#xff0c;但是大家还是要加油鸭&#…

kafka leader选举过程浅析

文章目录 概要核心概念leader选举具体流程小结 概要 kafka我们都知道它是通过副本机制&#xff0c;来支持负载均衡和故障转移等高可用的&#xff0c;那么具体副本的选举过程你了解吗&#xff1f;下面我们一起来学习下吧&#xff01; 核心概念 Controller定义&#xff1a;是特…

Cocos Creator2D游戏开发(7)-飞机大战(5)-让子弹飞

飞机大战(5)-碰撞及积分 参考敌机的生成 子弹由飞机生成,放在player_node节点子弹重复使用,要使用预制体;子弹新增了动画 ①创建一个预制体 命名为playerBullet_prefab ② 双击预制体将bullet1图片拖入预制体 保存,关闭(场景编辑器里面的) ③ 发射子弹 player加入代码 prop…

尚庭公寓(五)

图片上传管理 由于公寓、房间等实体均包含图片信息&#xff0c;所以在新增或修改公寓、房间信息时&#xff0c;需要上传图片&#xff0c;因此我们需要实现一个上传图片的接口。 **1. 图片上传流程** 下图展示了新增房间或公寓时&#xff0c;上传图片的流程。 可以看出图片上传…

翻译: 可视化深度学习神经网络二

并甚至在图像识别之外做各种各样智能的东西也许你也想分解成一些抽象的层 例如句子的分析涉及到把原始的语音提出一些独特的声音构成一些音节再构成词再构成词组以及更为抽象的思想等。 但回到这些实际是怎样工作的把你自己现在就放到这个的情景怎样来设计 如何在让这层中的激励…

阿里云主机 安装RabbitMQ

一、操作系统 用的是Alibaba Cloud Linux release 3 (Soaring Falcon)系统&#xff0c;可以通过命令&#xff1a;lsb_release -a 查看系统信息。 二、安装RabbitMQ RabbitMQ 是基于 Erlang 语言构建的&#xff0c;要安装RabbitMQ&#xff0c;需先安装Erlang环境。通过Erlang V…

SearchGPT:搜索引擎市场的潜在游戏规则改变者

关注公众号网络研究观获取更多内容。 OpenAI最近发布的SearchGPT原型标志着搜索技术领域的重大进展。我一直在等待这一天&#xff0c;任何关注搜索和搜索引擎优化领域的人也是如此。我们有充分的理由相信&#xff0c;这一举措很有可能颠覆长期由谷歌等巨头主导的搜索引擎市场&…

宠物医院预约系统-计算机毕业设计源码60818

目录 摘要 Abstract 第一章 绪论 1.1 选题背景及意义 1.2 国内外研究现状 1.3 研究方法 第二章 相关技术介绍 2.1 MySQL简介 2.2 Java编程语言 2.3 B/S模式 2.4 springboot框架 第三章 宠物医院预约系统 系统分析 3.1 系统目标 3.2 系统可行性分析 3.2.1 技术可行…

链式队列实现

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝唯有主动付出,才有丰富的果实获得收获! 在计算机科学中,队列是一种先进先出(FIFO, First In First Out)的数据结构…

.NET周刊【7月第4期 2024-07-28】

国内文章 .NET 高性能缓冲队列实现 BufferQueue https://mp.weixin.qq.com/s/fUhJpyPqwcmb3whuV3CDyg BufferQueue 是一个用 .NET 编写的高性能的缓冲队列实现&#xff0c;支持多线程并发操作。 项目地址&#xff1a;https://github.com/eventhorizon-cli/BufferQueue 项目…

Robot Operating System——远程修改日志等级

大纲 日志输出Node修改其他Node日志等级的Node获取日志等级设置日志等级 测试默认等级Debug等级Warn等级Error等级 完整代码 在任何系统中&#xff0c;日志功能的重要性都是不容忽视的。日志功能为开发者、维护者甚至用户提供了一个关键的工具&#xff0c;以监控、理解和调试系…

基于Windows Docker desktop搭建pwn环境

安装虚拟机很重&#xff0c;占空间&#xff0c;影响速度。 今天试了下用Windows下的Docker搭建pwn做题环境&#xff0c;搭配MobaXterm真的很好! 一、Windows下安装Docker desktop 网上参考文章很多&#xff0c;不赘述。 说明&#xff1a;去https://www.docker.com/products/d…

PHP经销商订货管理系统小程序源码

经销商订货管理系统&#xff1a;重塑供应链效率的利器 &#x1f680; 开篇&#xff1a;解锁供应链管理的新纪元 在竞争激烈的商业环境中&#xff0c;经销商作为供应链的关键一环&#xff0c;其订货效率直接影响到整个供应链的流畅度和响应速度。传统的订货方式往往繁琐、易出…

【C++深度探索】深入解析AVL树的底层实现机制

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;C从入门至进阶 这里将会不定期更新有关C/C的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 前言 AV…