恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
C++策略模式实现与优化技巧
首页
资讯中心
/
C++策略模式实现与优化技巧
C++策略模式实现与优化技巧
发布时间:2026/9/11 13:12:59
1. 策略模式基础与C实现策略模式是GoF设计模式中最常用的行为型模式之一它定义了算法家族将每个算法封装起来并使它们可以互相替换。这种模式让算法的变化独立于使用算法的客户端。在C中策略模式的经典实现通常包含三个核心组件Context上下文持有一个策略对象的引用Strategy抽象策略定义算法接口的抽象类或接口ConcreteStrategy具体策略实现具体算法的派生类// 抽象策略接口 class SortingStrategy { public: virtual void sort(vectorint data) 0; virtual ~SortingStrategy() default; }; // 具体策略类 class QuickSort : public SortingStrategy { public: void sort(vectorint data) override { // 快速排序实现 cout Sorting using QuickSort endl; // ...具体排序逻辑 } }; class MergeSort : public SortingStrategy { public: void sort(vectorint data) override { // 归并排序实现 cout Sorting using MergeSort endl; // ...具体排序逻辑 } }; // 上下文类 class Sorter { private: unique_ptrSortingStrategy strategy; public: explicit Sorter(unique_ptrSortingStrategy strategy) : strategy(move(strategy)) {} void setStrategy(unique_ptrSortingStrategy newStrategy) { strategy move(newStrategy); } void executeSort(vectorint data) { strategy-sort(data); } };这种基础实现虽然简单直接但在实际C项目中可能会遇到几个问题策略对象生命周期管理复杂运行时策略切换可能带来性能开销策略接口变更会导致所有具体策略需要修改提示在C11及以上版本中优先使用unique_ptr管理策略对象所有权避免裸指针带来的内存泄漏风险。2. 基于模板的策略模式变体2.1 编译时策略选择C模板元编程能力允许我们在编译时确定策略这种静态策略模式完全消除了运行时多态的开销template typename TStrategy class Sorter { public: void sort(vectorint data) { TStrategy strategy; strategy.sort(data); } }; // 策略作为模板参数 struct BubbleSort { void sort(vectorint data) { cout BubbleSort implementation endl; } }; // 使用示例 SorterBubbleSort sorter; sorter.sort(data);这种方式的优势零运行时开销编译器可以进行更好的优化策略接口检查在编译时完成缺点也很明显策略不能在运行时动态切换编译错误信息可能难以理解代码膨胀风险2.2 策略作为模板参数包C11引入的可变参数模板可以创建更灵活的策略组合template typename... Strategies class CompositeStrategy : public Strategies... { public: void sort(vectorint data) { // 应用所有策略 (Strategies::sort(data), ...); } }; // 使用示例 using MyStrategy CompositeStrategyQuickSort, MergeSort; SorterMyStrategy sorter; sorter.sort(data);这种模式特别适合需要应用多个策略链的场景比如数据处理的多个阶段。3. 基于std::function的策略模式现代C的std::function提供了另一种灵活的策略实现方式class Sorter { private: functionvoid(vectorint) strategy; public: explicit Sorter(functionvoid(vectorint) strat) : strategy(strat) {} void setStrategy(functionvoid(vectorint) newStrat) { strategy newStrat; } void executeSort(vectorint data) { strategy(data); } }; // 使用lambda表达式作为策略 Sorter sorter([](vectorint data) { cout Lambda sort strategy endl; // ...排序实现 });这种方式的优势策略可以是函数指针、lambda、函数对象等任何可调用对象不需要继承层次结构更简洁的语法注意std::function会有一定的类型擦除开销在性能关键路径上需要谨慎使用。4. 策略模式与C20概念C20引入的概念(Concepts)可以更好地约束策略接口template typename T concept SortingStrategy requires(T t, vectorint data) { { t.sort(data) } - same_asvoid; }; template SortingStrategy T class Sorter { T strategy; public: void sort(vectorint data) { strategy.sort(data); } };概念提供了比传统接口继承更灵活的约束方式同时保持了编译时检查的优势。5. 策略对象生命周期管理5.1 基于共享所有权的策略当策略需要在多个上下文间共享时可以使用shared_ptrclass Sorter { private: shared_ptrSortingStrategy strategy; public: explicit Sorter(shared_ptrSortingStrategy strat) : strategy(strat) {} // ...其他成员 };5.2 策略缓存与复用对于创建成本高的策略对象可以实现策略工厂进行缓存class StrategyFactory { private: unordered_mapstring, shared_ptrSortingStrategy cache; public: shared_ptrSortingStrategy getStrategy(const string name) { if (!cache.count(name)) { if (name quick) cache[name] make_sharedQuickSort(); else if (name merge) cache[name] make_sharedMergeSort(); } return cache[name]; } };6. 性能优化技巧6.1 小对象优化对于小型策略对象可以考虑避免动态内存分配class Sorter { private: SortingStrategy strategy; // 引用外部策略 public: explicit Sorter(SortingStrategy strat) : strategy(strat) {} // ... };6.2 策略内联模板策略可以被编译器内联优化template typename Strategy void sortWithStrategy(vectorint data, Strategy strat) { strat.sort(data); // 可能被内联 }7. 实际应用案例7.1 游戏AI行为策略class EnemyAI { public: virtual void update(Enemy enemy) 0; }; class AggressiveAI : public EnemyAI { /*...*/ }; class DefensiveAI : public EnemyAI { /*...*/ }; class Enemy { unique_ptrEnemyAI ai; public: void setAI(unique_ptrEnemyAI newAI) { ai move(newAI); } void update() { ai-update(*this); } };7.2 数据序列化策略class Serializer { public: virtual string serialize(const Data data) 0; }; class JSONSerializer : public Serializer { /*...*/ }; class XMLSerializer : public Serializer { /*...*/ }; class DataProcessor { unique_ptrSerializer serializer; public: void setSerializer(unique_ptrSerializer ser) { serializer move(ser); } string process(const Data data) { return serializer-serialize(data); } };8. 测试策略模式策略模式的一个主要优势是便于单元测试class MockStrategy : public SortingStrategy { public: bool wasCalled false; void sort(vectorint) override { wasCalled true; } }; TEST(SorterTest, ExecuteSortCallsStrategy) { auto mock make_uniqueMockStrategy(); auto* mockPtr mock.get(); Sorter sorter(move(mock)); vectorint testData; sorter.executeSort(testData); EXPECT_TRUE(mockPtr-wasCalled); }9. 常见问题与解决9.1 策略接口膨胀当策略接口方法过多时考虑使用命令模式或将策略拆分为多个更小的策略。9.2 策略组合爆炸使用策略工厂或组合模式来管理大量相关策略。9.3 线程安全问题如果策略会在多线程环境中被替换需要适当的同步机制class ThreadSafeSorter { mutex mtx; unique_ptrSortingStrategy strategy; public: void setStrategy(unique_ptrSortingStrategy newStrat) { lock_guardmutex lock(mtx); strategy move(newStrat); } // ... };10. 现代C中的最佳实践优先使用unique_ptr管理策略对象所有权考虑使用std::variant实现类型安全的策略集合对于性能关键路径评估静态策略模板的优势使用concept约束策略接口C20策略接口尽量保持小巧单一职责原则// 使用variant的示例 using StrategyVariant variantQuickSort, MergeSort, BubbleSort; class VariantSorter { StrategyVariant strategy; public: explicit VariantSorter(StrategyVariant strat) : strategy(move(strat)) {} void sort(vectorint data) { visit([data](auto s) { s.sort(data); }, strategy); } };在实际项目中策略模式的选择应该基于性能需求运行时vs编译时灵活性要求是否需要运行时切换代码复杂度约束团队熟悉程度我发现在大型C项目中混合使用静态和动态策略模式往往能取得最佳平衡 - 在性能关键路径使用模板策略在需要灵活配置的部分使用运行时多态策略。