策略模式(Strategy Pattern)

C++ 策略模式(Strategy Pattern)

一、模式基础定义

策略模式属于行为型设计模式

核心思想:将不同业务算法独立封装成策略类 ,算法与业务主体解耦,运行时可自由替换算法,摒弃臃肿if-else判断,严格遵循开闭原则、单一职责原则

适用核心场景:同一个行为存在多种实现方案,需要动态切换使用。

二、三大核心角色

角色 作用 C++ 实现形式
抽象策略 Strategy 定义统一算法接口,规范所有策略行为 抽象基类,包含纯虚函数
具体策略 ConcreteStrategy 实现各自独立算法逻辑,互不干扰 派生类,重写虚接口
上下文 Context 持有策略实例,对外统一调用入口,委托策略执行 聚合策略基类指针/智能指针

三、模式UML逻辑关系

  1. Context 聚合 Strategy 抽象类
  2. 多个 ConcreteStrategy 继承 Strategy
  3. 客户端操作 Context,动态注入不同具体策略
  4. 实际算法执行由具体策略类完成

四、经典面向对象实现(虚函数继承)

排序算法切换为业务案例

cpp 复制代码
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>

// 抽象策略类
class SortStrategy
{
public:
    virtual ~SortStrategy() = default;
    virtual void sortData(std::vector<int>& arr) = 0;
};

// 具体策略1:冒泡排序
class BubbleSortStrategy : public SortStrategy
{
public:
    void sortData(std::vector<int>& arr) override
    {
        int len = arr.size();
        for (int i = 0; i < len - 1; ++i)
        {
            for (int j = 0; j < len - 1 - i; ++j)
            {
                if (arr[j] > arr[j + 1])
                    std::swap(arr[j], arr[j + 1]);
            }
        }
        std::cout << "冒泡排序完成\n";
    }
};

// 具体策略2:快速排序
class QuickSortStrategy : public SortStrategy
{
public:
    void sortData(std::vector<int>& arr) override
    {
        std::sort(arr.begin(), arr.end());
        std::cout << "快速排序完成\n";
    }
};

// 具体策略3:插入排序
class InsertSortStrategy : public SortStrategy
{
public:
    void sortData(std::vector<int>& arr) override
    {
        int len = arr.size();
        for (int i = 1; i < len; ++i)
        {
            int temp = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > temp)
            {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = temp;
        }
        std::cout << "插入排序完成\n";
    }
};

// 上下文环境类
class SortContext
{
private:
    std::unique_ptr<SortStrategy> strategy;
public:
    // 动态设置策略
    void setStrategy(std::unique_ptr<SortStrategy> st)
    {
        strategy = std::move(st);
    }
    // 对外统一执行接口
    void executeSort(std::vector<int>& arr)
    {
        if (strategy)
            strategy->sortData(arr);
    }
};

// 客户端调用
int main()
{
    SortContext context;
    std::vector<int> nums = {5, 2, 9, 1, 5, 6};

    // 切换冒泡排序
    context.setStrategy(std::make_unique<BubbleSortStrategy>());
    context.executeSort(nums);

    // 切换快速排序
    context.setStrategy(std::make_unique<QuickSortStrategy>());
    context.executeSort(nums);

    // 切换插入排序
    context.setStrategy(std::make_unique<InsertSortStrategy>());
    context.executeSort(nums);

    return 0;
}

五、现代C++轻量化实现(std::function 无继承)

无需定义抽象基类与派生类,适合无状态简单策略,代码极简,常用于折扣计算、权限校验、简单规则判断。

cpp 复制代码
#include <iostream>
#include <functional>
#include <iomanip>

// 上下文类
class PriceContext
{
public:
    using DiscountFunc = std::function<double(double)>;
    explicit PriceContext(DiscountFunc func) : discountFunc(std::move(func)) {}

    // 动态更换折扣策略
    void changeStrategy(DiscountFunc func)
    {
        discountFunc = std::move(func);
    }

    // 计算最终价格
    double getFinalPrice(double originPrice)
    {
        return discountFunc(originPrice);
    }

private:
    DiscountFunc discountFunc;
};

int main()
{
    std::cout << std::fixed << std::setprecision(2);
    // 原价策略
    PriceContext ctx([](double p) { return p; });
    std::cout << "原价:" << ctx.getFinalPrice(800) << std::endl;

    // 9折优惠
    ctx.changeStrategy([](double p) { return p * 0.9; });
    std::cout << "9折价格:" << ctx.getFinalPrice(800) << std::endl;

    // 满减策略
    ctx.changeStrategy([](double p) { return p >= 500 ? p - 100 : p; });
    std::cout << "满减价格:" << ctx.getFinalPrice(800) << std::endl;

    return 0;
}

六、工程级扩展:策略工厂模式结合

项目中策略繁多时,通过工厂统一创建策略,字符串匹配获取对应算法,消除客户端new操作,便于配置文件读取策略。

cpp 复制代码
#include <unordered_map>
#include <functional>

// 策略工厂
class StrategyFactory
{
public:
    using StrategyCreator = std::function<std::unique_ptr<SortStrategy>()>;

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

    // 注册策略
    void registerStrategy(const std::string& name, StrategyCreator creator)
    {
        strategyMap[name] = std::move(creator);
    }

    // 获取策略实例
    std::unique_ptr<SortStrategy> createStrategy(const std::string& name)
    {
        if (strategyMap.find(name) != strategyMap.end())
            return strategyMap[name]();
        return nullptr;
    }

private:
    StrategyFactory() = default;
    std::unordered_map<std::string, StrategyCreator> strategyMap;
};

// 初始化注册策略
void initStrategy()
{
    auto& factory = StrategyFactory::getInstance();
    factory.registerStrategy("bubble", [](){return std::make_unique<BubbleSortStrategy>();});
    factory.registerStrategy("quick", [](){return std::make_unique<QuickSortStrategy>();});
}

七、模式核心优缺点

优点

  1. 算法与业务解耦,算法独立维护修改
  2. 完美符合开闭原则,新增策略无需改动原有代码
  3. 消除大量if/else分支代码,可读性大幅提升
  4. 运行时动态切换策略,灵活适配不同业务场景
  5. 策略类职责单一,单元测试方便

缺点

  1. 策略数量多会产生大量派生类,增加代码体量
  2. 客户端必须了解所有策略差异,才能合理选择
  3. 虚函数调用存在轻微运行开销,超高性能场景受限
  4. 策略之间无法共享局部数据

八、典型适用场景

  1. 同一功能存在多种算法实现:排序、加密、压缩、解析
  2. 商城多种优惠规则:折扣、满减、优惠券、积分抵扣
  3. 支付方式切换:微信、支付宝、银行卡支付
  4. 路由、权限、日志输出、数据导出格式切换
  5. 游戏技能、战斗模式、AI行为策略切换

九、易混淆设计模式对比

1. 策略模式 VS 状态模式

  • 策略:客户端主动选择算法,算法间平等替换
  • 状态:对象内部状态自动流转,被动切换行为

2. 策略模式 VS 模板方法

  • 策略:组合关系,整体替换整套算法
  • 模板方法:继承关系,仅重写算法局部步骤

3. 策略模式 VS 简单工厂

  • 策略:侧重算法行为切换
  • 工厂:侧重对象创建封装

十、C++ 开发最佳实践规范

  1. 优先使用unique_ptr智能指针管理策略生命周期,杜绝内存泄漏
  2. 策略类设计为无状态,不保存成员变量数据,提升复用性
  3. 简单规则用std::function+lambda,复杂算法使用继承策略
  4. 策略数量超过3个,建议搭配工厂统一管理创建
  5. 上下文设置默认策略,避免空指针调用崩溃
  6. 策略接口设计精简,减少参数耦合
  7. 禁止在策略类中调用业务上下文私有成员

十一、模式总结

策略模式本质封装变化点 ,把易变动的算法抽离为独立策略,固定不变的业务流程放在上下文。

C++ 中可根据项目复杂度,灵活选用继承虚函数 传统写法或函数对象轻量化写法,是日常开发替换条件分支、优化代码结构最常用的行为模式。

相关推荐
一个在高校打杂的5 天前
honeypot之opencanary(轻量化蜜罐)
linux·网络安全·网络攻击模型·安全威胁分析·策略模式
蜡笔小马6 天前
13.C++设计模式-策略模式
c++·设计模式·策略模式
杜子不疼.7 天前
【C++ AI 大模型接入 SDK】 - LLMProvider 抽象基类与策略模式
开发语言·c++·策略模式
代码对我眨眼睛8 天前
Mac 如何单独修改鼠标滚动方向,而不影响触控板
macos·计算机外设·策略模式
jiushiaifenxiang8 天前
Parallels Desktop for Mac 26.3.2 (57398)中文版新功能介绍
macos·策略模式
雪碧聊技术9 天前
什么是策略模式?一文详解
策略模式
johnny23311 天前
终端文件管理器:Yazi、nnn、Superfile、lf、Ranger、walk
策略模式
AI砖家11 天前
DeepSeek TUI 保姆级安装配置全指南 -Windows||macOS双平台全覆盖
服务器·前端·人工智能·windows·macos·ai编程·策略模式
有梦想的小何11 天前
Cursor AI 编程实战(篇三):Domain、Infrastructure 与策略模式
java·ai编程·策略模式