当前位置: 首页 > backend >正文

【C++设计模式之Strategy策略模式】

C++设计模式之Strategy策略模式

  • 模式定义
  • 核心思想
  • 动机(Motivation)
  • 结构(Structure)
  • 实现步骤
    • 1. 定义策略接口(基于继承)
    • 2.实现具体策略
    • 3.上下文类(Context)
    • 4. 在main中调用
  • 应用场景(基于继承)
    • 1.定义策略接口
    • 2.实现具体策略
    • 3.上下文类(Context)
    • 4.在main中调用测试
  • 现代 C++ 优化(基于 std::function)
    • 1.使用函数对象替代接口
    • 2.定义策略函数
    • 3.main.cpp中使用示例
  • 优化方向
    • 1.编译时策略(模板实现)
    • 2.线程安全策略切换
  • 要点总结


模式定义

策略模式:定义一系列算法,把她们一个个封装起来,并且使它们可以相互替换(变化)。该模式使得算法可以独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
需要区分策略模式和之前提到的模板方法模式的不同,模板方法是通过继承来改变部分步骤,而策略模式是通过组合不同的策略对象来改变整体行为。

核心思想

  • 解耦算法与客户端:将算法逻辑从主类中分离,避免代码臃肿。
  • 运行时动态切换:通过更换策略对象,灵活改变程序行为。
  • 开闭原则:新增算法无需修改现有代码,只需添加新策略类。

动机(Motivation)

  • 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。
  • 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

结构(Structure)

在这里插入图片描述

实现步骤

1. 定义策略接口(基于继承)

startegy.h

#pragma once
class Strategy {//策略模式的运算法则
public:virtual ~Strategy() {}virtual void doSomething() = 0;
};

2.实现具体策略

concretestrategy.h

#pragma once
#include<iostream>
#include"strategy.h"
class ConcreteStrategy1 :public Strategy {
public:void doSomething()override {std::cout << "ConcreteStrategy1 doSomething" << std::endl;}
};class ConcreteStrategy2 :public Strategy {
public:void doSomething()override {std::cout << "ConcreteStrategy2 doSomething" << std::endl;}
};

3.上下文类(Context)

持有策略对象的引用,并委托算法执行

context.h

#pragma once
#include"strategy.h"
class Context {
public://构造函数设置具体策略Context(Strategy *strategy) {strategy_ = strategy;}//封装后的策略方法void doAnything() {strategy_->doSomething();}private:Strategy *strategy_ = nullptr;
};

4. 在main中调用

#include "concretestrategy.h"
#include "context.h"int main()
{Strategy *strategy = new ConcreteStrategy1();//声明上下文对象Context context(strategy);context.doAnything();delete strategy;
}

应用场景(基于继承)

传统实现(基于继承),实现快速排序算法,归并排序算法的策略模式

1.定义策略接口

sortingstrategy.h

#pragma once
#include<iostream>
#include<vector>//策略接口:定义算法的抽象操作
class SortingStrategy {
public:virtual ~SortingStrategy() = default;virtual void sort(std::vector<int>&data)const = 0;
};

2.实现具体策略

#pragma once
#include"sortingstrategy.h"
//具体策略1:快速排序
class QuickSort :public SortingStrategy
{
public:void sort(std::vector<int>&data)const override {std::cout << "Sorting with QuickSort\n";//快速排序具体实现}
};class MergeSort :public SortingStrategy
{
public:void sort(std::vector<int>&data)const override {std::cout << "Sorting with MergeSort\n";//归并排序具体实现}
};

3.上下文类(Context)

持有策略对象的引用,并委托算法执行

context.h

#pragma once
#include"concretesorting.h"
class Sorter {
private:std::unique_ptr<SortingStrategy> strategy_;  //使用智能指针管理策略对象public:explicit Sorter(std::unique_ptr<SortingStrategy> strategy):strategy_(std::move(strategy)){}//动态切换策略void setStrategy(std::unique_ptr<SortingStrategy>strategy) {strategy_ = std::move(strategy);}//执行排序void executeSort(std::vector<int>&data)const {if (strategy_) {strategy_->sort(data);}}
};

4.在main中调用测试

#include"context.h"
#include<vector>int main()
{std::vector<int> data = { 5,2,7,1,9 };Sorter sorter(std::make_unique<QuickSort>());sorter.executeSort(data);    //输出:Sorting with QuickSortsorter.setStrategy(std::make_unique<MergeSort>());sorter.executeSort(data);    //输出Sorting with MergeSortreturn 0;
}

现代 C++ 优化(基于 std::function)

1.使用函数对象替代接口

无需继承策略接口,直接通过std::function封装算法:
context.h

#pragma once
#include<functional>
#include<vector>class Sorter {
public:using Strategy = std::function<void(std::vector<int>&)>;explicit Sorter(Strategy strategy):strategy_(std::move(strategy)){}void setStrategy(Strategy strategy) {strategy_ = std::move(strategy);}void executeSort(std::vector<int>&data)const {if (strategy_) {strategy_(data);}}private:Strategy strategy_;
};

2.定义策略函数

context.h

void quickSort(std::vector<int>& data) {std::cout << "Sorting with QuickSort\n";// 快速排序实现...
}void mergeSort(std::vector<int>& data) {std::cout << "Sorting with MergeSort\n";// 归并排序实现...
}// 支持 Lambda 表达式
auto bubbleSort = [](std::vector<int>& data) {std::cout << "Sorting with BubbleSort\n";// 冒泡排序实现...
};

3.main.cpp中使用示例

#include"context.h"int main()
{std::vector<int> data = { 5,2,7,1,9 };Sorter sorter(quickSort);sorter.executeSort(data);      //输出Sorting with QuickSortsorter.setStrategy(mergeSort); //输出Sorting with MergeSortsorter.executeSort(data);sorter.setStrategy(bubbleSort);//输出Sorting with BubbleSortsorter.executeSort(data);//直接传达Lambdasorter.setStrategy([](std::vector<int>&data) {std::cout << "Custom Lambda Strategy \n";});sorter.executeSort(data);return 0;
}

优化方向

1.编译时策略(模板实现)

通过模板参数在编译时绑定 策略,消除运行时开销:

#pragma once
#include<vector>
#include<iostream>template<typename Strategy>
class ComplieTimeSorter {
public:void executeSort(std::vector<int>&data)const {Strategy::sort(data);   //策略需要提供静态方法}
};//策略类无需继承接口
struct QuickSort {static void sort(std::vector<int>&data) {std::cout << "Compile-Time QuickSort \n";}
};int main()
{std::vector<int> data = { 5,2,7,1,9 };ComplieTimeSorter<QuickSort>sorter;sorter.executeSort(data);  //输出Complie-Time QuickSortsystem("pause");return 0;
}

2.线程安全策略切换

在多线程环境中安全且策略:

#pragma once
#include<mutex>
#include<vector>class ThreadSafeSorter {
public:using Strategy = std::function<void(std::vector<int>&)>;void setStrategy(Strategy strategy) {std::lock_guard<std::mutex>lock(mtx_);strategy_ = std::move(strategy);}void executeSort(std::vector<int>&data)const {std::lock_guard<std::mutex>lock(mtx_);if (strategy_) {strategy_(data);}}
private:mutable std::mutex mtx_;Strategy strategy_;
};

要点总结

  • Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。
  • Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。
http://www.xdnf.cn/news/5022.html

相关文章:

  • ISP流程介绍(Rgb格式阶段)
  • Java 原生实现代码沙箱(OJ判题系统第1期)——设计思路、实现步骤、代码实现
  • MySQL——七、索引
  • ArrayList和LinkedList区别
  • nginx的学习笔记
  • Android屏蔽通话功能和短信功能
  • AD 电阻容模型的创建
  • 68、微服务保姆教程(十一)微服务的监控与可观测性
  • 乌班图安装docker
  • 1.3.2 linux音频PulseAudio详细介绍
  • 关系模式-无损连接和保持函数依赖的判断
  • 用Python解密霍格沃茨的情感密码:哈利波特系列文本挖掘之旅
  • 用 Java 实现一个简单的阻塞队列
  • HTML字符串转换为React元素实现
  • 云轴科技ZStack入选赛迪顾问2025AI Infra平台市场发展报告代表厂商
  • LeetCode 1722. 执行交换操作后的最小汉明距离 题解
  • Filecoin存储管理:如何停止Lotus向特定存储路径写入新扇区数据
  • 【杂谈】-认知的范式革命:从逻辑理性到类比思维
  • 什么是AI写作
  • Rust 中的 Pin 和 Unpin:内存安全与异步编程的守护者
  • Typora+PicGo+Gitee图床配置教程 自动图片上传
  • WebRTC工作原理详细介绍、WebRTC信令交互过程和WebRTC流媒体传输协议介绍
  • RabittMQ-高级特性2-应用问题
  • 8.1.Kubernetes进阶
  • 使用零样本LLM在现实世界环境中推广端到端自动驾驶——论文阅读
  • tauri-plugin-store 这个插件将数据存在本地电脑哪个位置
  • ROS快速入门教程06
  • 在windows系统中安装图数据库NEO4J
  • vLLM部署Qwen2-7B模型推理
  • AI-02a5a4.神经网络-与学习相关的技巧-参数更新