C++ 设计模式 - 策略模式

news/2025/2/22 16:04:15

一:概述

        策略模式是一种行为设计模式,来源于《设计模式:可复用面向对象软件的基础》一书。它定义了一组算法,并将它们封装成独立的对象。策略模式在标准模板库(STL)中被广泛使用。

二:策略模式的设计实现

      目的
            定义一组算法,并将它们封装成对象。

      别名
            策略(Policy)

      使用场景

          1)需要多种不同版本的算法。

          2)客户端不需要了解具体的算法实现。

         3)需要在程序运行时能够切换算法。

        

1. 策略(Strategy)

       为一组算法定义接口。

2. 具体策略(ConcreteStrategy)

       实现某个具体的算法。

3. 上下文(Context)

      维护对具体策略(ConcreteStrategy)的引用。

      持有一个具体策略(ConcreteStrategy)。

上下文(Context)持有一个封装在对象中的具体策略(ConcreteStrategy)。具体策略实现了策略(Strategy)接口。通常,具体策略可以在程序运行时进行调整。

#include <iostream>
#include <memory>
#include <utility>

// 抽象策略类,定义策略接口
class Strategy {
public:
    virtual void execute() = 0;  // (4) 纯虚函数,具体策略类需要实现此方法
    virtual ~Strategy() {}       // 虚析构函数,保证子类正确析构
};

// 上下文类,负责管理和执行策略
class Context {
    std::unique_ptr<Strategy> strat{};  // (1) 使用智能指针管理策略对象,确保资源自动释放
public:                                                   
    void setStrategy(std::unique_ptr<Strategy> strat_) {  // (2) 设置策略,使用 std::move 进行所有权转移
        strat = std::move(strat_);
    }
    
    void strategy() {  // (3) 执行当前策略(如果存在)
        if (strat) strat->execute();
    }
};

// 具体策略1,实现 execute 方法
class Strategy1 : public Strategy {
public:
    void execute() override {  // override 关键字确保正确重写基类方法
        std::cout << "Strategy1 executed\n";
    }
};

// 具体策略2,实现 execute 方法
class Strategy2 : public Strategy {
public:
    void execute() override {
        std::cout << "Strategy2 executed\n";
    }
};

// 具体策略3,实现 execute 方法
class Strategy3 : public Strategy {
public:
    void execute() override {
        std::cout << "Strategy3 executed\n";
    }
};

int main() {
    std::cout << '\n';

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

    // 设置并执行策略1
    k.setStrategy(std::make_unique<Strategy1>());
    k.strategy();

    // 设置并执行策略2
    k.setStrategy(std::make_unique<Strategy2>());
    k.strategy();

    // 设置并执行策略3
    k.setStrategy(std::make_unique<Strategy3>());
    k.strategy();

    std::cout << '\n';

    return 0;
}

三:策略模式在C++标准库中的应用 

template<class T, class Allocator = std::allocator<T>>          // (1)
class vector; 

template<class Key,
    class T,
    class Hash = std::hash<Key>,                               // (3)
    class KeyEqual = std::equal_to<Key>,                       // (4)
    class allocator = std::allocator<std::pair<const Key, T>>  // (2)
class unordered_map;

      策略模式在 STL 中被广泛应用,主要用于允许用户自定义算法或策略,以适应不同的需求。例如,STL 容器 std::vectorstd::unordered_map 使用 模板参数 作为策略对象,提供了灵活的内存管理、哈希计算等策略的自定义能力。

策略模式的体现:

  1. 哈希函数可替换:如果默认的 std::hash<Key> 不能满足需求(如哈希冲突太多),可以提供自定义哈希函数。
  2. 键比较策略可替换:如果键的比较方式需要修改(如忽略大小写),可以自定义 KeyEqual
  3. 内存分配策略可替换:默认的 std::allocator 可以替换为其他自定义分配器。

四:策略模式的优缺点

   优点

  • 算法被封装成对象,并且可以在运行时进行替换。
  • 添加新的策略非常容易,只需实现一个新的策略类即可。
  • 策略模式可以替代基于 if/elseswitch 语句的条件执行,提高代码的可维护性和扩展性。
  • 在 C++ 中,可调用对象(Callables)通常是策略的轻量级实现。

  缺点

  • 客户端必须了解并选择合适的策略。
  • 可能会导致对象(策略)数量急剧增加。

http://www.niftyadmin.cn/n/5862500.html

相关文章

NeurIPS-2024 | 具身智能如何理解空间关系?SpatialRGPT:视觉语言模型中的具象空间推理

作者&#xff1a;An-Chieh Cheng, Hongxu Yin, Yang Fu, Qiushan Guo, Ruihan Yang, Jan Kautz, Xiaolong Wang, Sifei Liu 单位&#xff1a;加州大学圣地亚哥分校&#xff0c;NVIDIA 标题&#xff1a;SpatialRGPT: Grounded Spatial Reasoning in Vision-Language Models 原…

5G-A的尔滨故事,冰雪下的科技春潮

刚刚结束的第九届亚冬会中&#xff0c;黑科技5G-A达成了刷屏级的效果。这也是5G-A首次大规模服务于国际大型体育赛事。 一场冰雪盛会之后&#xff0c;5G-A向何处去&#xff1f;这个黑科技的能力&#xff0c;将如何投放给大众消费者和企业&#xff1f;这是值得我们进一步思考的话…

GlusterFS卷管理实战指南:从扩展卷到自我修复,全面掌握高效运维技巧

#作者&#xff1a;闫乾苓 文章目录 1 扩展卷2 收缩卷3 更换故障brick3.1 更换纯分布式中的brick3.2 更换复制/分布式复制卷中的brick 4 重新平衡卷4.1 重新平衡卷以修复布局变化4.2 重新平衡卷以修复布局并迁移现有数据4.3 显示重新平衡操作的状态4.4 停止正在进行的重新平衡操…

Ae:导入 3D 模型

在 After Effects 24.1 及更高版本中&#xff0c;可以直接将 3D 模型 3D Model导入到项目&#xff0c;并将其与其他 2D 和 3D 图层一起放入合成中。 3D 模型文件主要是通过描述几何结构、材质和纹理、动画、光源与摄像机、场景结构、物理属性&#xff08;某些文件格式&#xff…

LangChain:AI大模型开发与分布式系统设计

文章目录 第一部分&#xff1a;大模型与 LangChain 基础1.1 大语言模型概述1.2 LangChain 基础 第二部分&#xff1a;模型初始化与调用2.1 自定义大模型架构 第三部分&#xff1a;高级模型设计与优化3.1 提示工程与模型调优3.2 高效处理大规模数据 第四部分&#xff1a;分布式系…

Docker-技术架构演进之路

目录 一、概述 常见概念 二、架构演进 1.单机架构 2.应用数据分离架构 3.应用服务集群架构 4.读写分离 / 主从分离架构 5.引入缓存 —— 冷热分离架构 6.垂直分库 7.业务拆分 —— 微服务 8.容器化引入——容器编排架构 三、尾声 一、概述 在进行技术学习过程中&am…

蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)

Day 4&#xff1a;背包问题、最长递增子序列&#xff08;LIS&#xff09; &#x1f4d6; 一、动态规划&#xff08;Dynamic Programming&#xff09;简介 动态规划是一种通过将复杂问题分解成更小的子问题来解决问题的算法设计思想。它主要用于解决具有最优子结构和重叠子问题…