ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C++策略模式详解:原理、实现与应用场景

C++策略模式详解:原理、实现与应用场景 1. 策略模式基础概念解析策略模式(Strategy Pattern)是GoF设计模式中行为型模式的经典代表它定义了算法家族并分别封装起来让它们之间可以互相替换。这种模式的核心在于将算法的使用与实现分离使得算法可以独立于使用它的客户端变化。在C中实现策略模式通常包含三个关键角色环境类(Context)持有一个策略类的引用最终给客户端调用抽象策略类(Strategy)定义所有支持的算法的公共接口具体策略类(ConcreteStrategy)实现了抽象策略定义的接口提示策略模式特别适合处理同一问题存在多种解决方案的场景比如排序算法选择、支付方式切换等业务场景。2. C策略模式实现详解2.1 基础实现框架以下是策略模式在C中的典型实现框架// 抽象策略类 class Strategy { public: virtual ~Strategy() default; virtual void execute() const 0; }; // 具体策略A class ConcreteStrategyA : public Strategy { public: void execute() const override { std::cout Executing Strategy A\n; } }; // 具体策略B class ConcreteStrategyB : public Strategy { public: void execute() const override { std::cout Executing Strategy B\n; } }; // 环境类 class Context { private: std::unique_ptrStrategy strategy_; public: explicit Context(std::unique_ptrStrategy strategy) : strategy_(std::move(strategy)) {} void setStrategy(std::unique_ptrStrategy strategy) { strategy_ std::move(strategy); } void executeStrategy() const { strategy_-execute(); } };2.2 现代C实现优化现代C(C11及以上)提供了更多工具来优化策略模式的实现使用std::function替代继承体系class Context { private: std::functionvoid() strategy_; public: explicit Context(std::functionvoid() strategy) : strategy_(std::move(strategy)) {} void setStrategy(std::functionvoid() strategy) { strategy_ std::move(strategy); } void executeStrategy() const { strategy_(); } };结合lambda表达式使用Context ctx([](){ std::cout Lambda strategy\n; }); ctx.executeStrategy();3. 策略模式实战应用案例3.1 排序算法选择器假设我们需要实现一个排序工具支持多种排序算法动态切换// 排序策略接口 class SortStrategy { public: virtual ~SortStrategy() default; virtual void sort(std::vectorint data) const 0; }; // 具体排序策略 class QuickSort : public SortStrategy { public: void sort(std::vectorint data) const override { std::cout Quick sorting...\n; // 实际快速排序实现 } }; class MergeSort : public SortStrategy { public: void sort(std::vectorint data) const override { std::cout Merge sorting...\n; // 实际归并排序实现 } }; // 排序上下文 class Sorter { private: std::unique_ptrSortStrategy strategy_; public: explicit Sorter(std::unique_ptrSortStrategy strategy) : strategy_(std::move(strategy)) {} void setStrategy(std::unique_ptrSortStrategy strategy) { strategy_ std::move(strategy); } void executeSort(std::vectorint data) { strategy_-sort(data); } };3.2 电商支付系统设计电商平台通常需要支持多种支付方式策略模式非常适合这种场景// 支付策略接口 class PaymentStrategy { public: virtual ~PaymentStrategy() default; virtual void pay(double amount) const 0; }; // 具体支付策略 class CreditCardPayment : public PaymentStrategy { public: void pay(double amount) const override { std::cout Paying amount via Credit Card\n; } }; class PayPalPayment : public PaymentStrategy { public: void pay(double amount) const override { std::cout Paying amount via PayPal\n; } }; // 支付上下文 class PaymentProcessor { private: std::unique_ptrPaymentStrategy strategy_; public: explicit PaymentProcessor(std::unique_ptrPaymentStrategy strategy) : strategy_(std::move(strategy)) {} void setStrategy(std::unique_ptrPaymentStrategy strategy) { strategy_ std::move(strategy); } void executePayment(double amount) { strategy_-pay(amount); } };4. 策略模式的高级应用技巧4.1 策略对象创建优化频繁创建策略对象可能带来性能开销可以考虑以下优化方案策略对象复用class StrategyFactory { private: std::unordered_mapstd::string, std::shared_ptrStrategy strategies_; public: StrategyFactory() { strategies_[A] std::make_sharedConcreteStrategyA(); strategies_[B] std::make_sharedConcreteStrategyB(); } std::shared_ptrStrategy getStrategy(const std::string type) { return strategies_.at(type); } };使用轻量级策略对象class StatelessStrategy { public: void operator()() const { std::cout Stateless strategy\n; } }; Context ctx(StatelessStrategy{}); ctx.executeStrategy();4.2 策略组合模式有时需要组合多个策略来实现复杂行为class CompositeStrategy : public Strategy { private: std::vectorstd::shared_ptrStrategy strategies_; public: void addStrategy(std::shared_ptrStrategy strategy) { strategies_.push_back(strategy); } void execute() const override { for (const auto strategy : strategies_) { strategy-execute(); } } };5. 策略模式的最佳实践与陷阱规避5.1 何时使用策略模式策略模式特别适用于以下场景一个系统需要动态地在几种算法中选择一种需要避免使用多重条件转移语句(if-else/switch-case)算法的使用者不需要知道具体的算法实现细节系统中有多个类只有算法行为不同5.2 常见陷阱与解决方案策略对象生命周期管理注意使用原始指针可能导致内存泄漏建议使用智能指针(std::unique_ptr/std::shared_ptr)管理策略对象生命周期策略接口膨胀 解决方案将大接口拆分为多个小接口遵循接口隔离原则策略与上下文过度耦合 解决方案通过依赖注入传递策略对象避免上下文直接实例化具体策略性能考虑 对于简单策略考虑使用函数指针或std::function替代虚函数调用5.3 测试策略模式策略模式的一个显著优势是便于单元测试// 测试专用策略 class MockStrategy : public Strategy { public: MOCK_METHOD(void, execute, (), (const, override)); }; TEST(StrategyTest, ExecuteCalled) { MockStrategy mock; EXPECT_CALL(mock, execute()).Times(1); Context ctx(mock); ctx.executeStrategy(); }6. 策略模式与其他模式的关系6.1 与工厂模式的结合策略模式常与工厂模式配合使用实现策略对象的创建与管理分离class StrategyFactory { public: static std::unique_ptrStrategy create(const std::string type) { if (type A) return std::make_uniqueConcreteStrategyA(); if (type B) return std::make_uniqueConcreteStrategyB(); throw std::invalid_argument(Unknown strategy type); } }; // 使用示例 auto strategy StrategyFactory::create(A); Context ctx(std::move(strategy));6.2 与模板方法的区别模板方法模式在父类中定义算法框架而策略模式将整个算法封装为独立对象。前者通过继承实现行为变化后者通过组合实现。6.3 与命令模式的对比命令模式将请求封装为对象支持撤销、队列等操作策略模式专注于算法的封装与替换。两者结构相似但意图不同。7. C20中的策略模式新写法C20引入的新特性可以进一步简化策略模式的实现使用概念(Concepts)约束策略类型template typename S concept StrategyConcept requires(S s) { { s.execute() } - std::same_asvoid; }; template StrategyConcept S class Context { private: S strategy_; public: explicit Context(S strategy) : strategy_(strategy) {} void executeStrategy() const { strategy_.execute(); } };使用协程实现异步策略class AsyncStrategy { public: std::futurevoid execute() const { co_await std::suspend_always{}; std::cout Async strategy\n; } };在实际项目中我发现策略模式特别适合处理业务规则频繁变化的场景。通过将业务规则封装为策略对象可以在不修改核心逻辑的情况下灵活应对需求变更。例如在金融系统中不同客户可能需要应用不同的计费策略使用策略模式可以优雅地实现这一需求。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进