ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

C++策略模式详解:实现方式与应用场景 1. 策略模式核心概念解析策略模式是行为型设计模式中最实用的模式之一它通过将算法族封装成独立的类使它们能够相互替换。这种模式让算法的变化独立于使用算法的客户端完美体现了开闭原则。在C中实现策略模式时通常会看到以下核心组件Strategy接口定义所有支持的算法族的公共接口ConcreteStrategy实现Strategy接口的具体算法类Context持有一个Strategy对象的引用通过委托调用具体算法关键理解策略模式不是简单地封装算法而是建立了一套可插拔的算法交换机制。这种机制在运行时通过多态实现动态切换而不是通过条件判断语句硬编码。2. C实现策略模式的三种经典方式2.1 基于继承的标准实现这是最教科书式的实现方式直接对应设计模式原教旨主义的实现class SortingStrategy { public: virtual ~SortingStrategy() default; virtual void sort(vectorint data) 0; }; class QuickSort : public SortingStrategy { public: void sort(vectorint data) override { cout Using quick sort endl; // 快速排序实现 } }; class MergeSort : public SortingStrategy { public: void sort(vectorint data) override { cout Using merge sort endl; // 归并排序实现 } }; class Sorter { unique_ptrSortingStrategy strategy; public: explicit Sorter(unique_ptrSortingStrategy s) : strategy(move(s)) {} void setStrategy(unique_ptrSortingStrategy s) { strategy move(s); } void executeSort(vectorint data) { if(strategy) { strategy-sort(data); } } };2.2 基于函数指针的轻量实现对于简单场景可以使用函数指针避免虚函数开销using SortFunc void(*)(vectorint); void quickSort(vectorint data) { // 快速排序实现 } void mergeSort(vectorint data) { // 归并排序实现 } class Sorter { SortFunc strategy nullptr; public: explicit Sorter(SortFunc f) : strategy(f) {} void setStrategy(SortFunc f) { strategy f; } void executeSort(vectorint data) { if(strategy) { strategy(data); } } };2.3 基于std::function的现代实现C11之后更推荐使用std::function它比函数指针更灵活class Sorter { functionvoid(vectorint) strategy; public: explicit Sorter(functionvoid(vectorint) f) : strategy(f) {} void setStrategy(functionvoid(vectorint) f) { strategy f; } void executeSort(vectorint data) { if(strategy) { strategy(data); } } }; // 使用lambda表达式 Sorter sorter([](vectorint data) { // 自定义排序逻辑 });3. 策略模式的五大实战应用场景3.1 算法选择器最常见的应用场景是运行时算法选择。比如图形渲染中根据硬件能力选择不同的渲染策略class RenderStrategy { public: virtual void render(const Scene scene) 0; }; class DirectXRenderer : public RenderStrategy { // DX实现 }; class OpenGLRenderer : public RenderStrategy { // OpenGL实现 }; class VulkanRenderer : public RenderStrategy { // Vulkan实现 }; class GraphicsEngine { unique_ptrRenderStrategy renderer; public: void setRenderer(unique_ptrRenderStrategy r) { renderer move(r); } void renderFrame(const Scene scene) { renderer-render(scene); } };3.2 业务规则引擎电商系统中的折扣策略是经典案例class DiscountStrategy { public: virtual double applyDiscount(double price) 0; }; class RegularDiscount : public DiscountStrategy { double applyDiscount(double price) override { return price * 0.9; } }; class VIPDiscount : public DiscountStrategy { double applyDiscount(double price) override { return price * 0.7; } }; class Order { unique_ptrDiscountStrategy discount; double total; public: void setDiscount(unique_ptrDiscountStrategy d) { discount move(d); } double checkout() { return discount ? discount-applyDiscount(total) : total; } };3.3 游戏AI行为游戏NPC的不同行为模式class AIBehavior { public: virtual void update(NPC npc) 0; }; class AggressiveBehavior : public AIBehavior { void update(NPC npc) override { // 攻击玩家逻辑 } }; class DefensiveBehavior : public AIBehavior { void update(NPC npc) override { // 防御逻辑 } }; class NPCharacter { unique_ptrAIBehavior behavior; public: void setBehavior(unique_ptrAIBehavior b) { behavior move(b); } void update() { behavior-update(*this); } };3.4 数据序列化支持多种格式的数据导出class Serializer { public: virtual string serialize(const Data data) 0; }; class JSONSerializer : public Serializer { string serialize(const Data data) override { // JSON序列化实现 } }; class XMLSerializer : public Serializer { string serialize(const Data data) override { // XML序列化实现 } }; class DataExporter { unique_ptrSerializer serializer; public: void setSerializer(unique_ptrSerializer s) { serializer move(s); } string exportData(const Data data) { return serializer-serialize(data); } };3.5 单元测试模拟测试中使用策略模式注入模拟对象class Database { public: virtual User getUser(int id) 0; }; class RealDatabase : public Database { User getUser(int id) override { // 真实数据库查询 } }; class MockDatabase : public Database { User getUser(int id) override { return User{id, Test User}; } }; class UserService { unique_ptrDatabase db; public: explicit UserService(unique_ptrDatabase d) : db(move(d)) {} User getUser(int id) { return db-getUser(id); } };4. 策略模式的高级应用技巧4.1 策略组合模式多个策略可以组合使用形成更复杂的行为class LogStrategy { public: virtual void log(const string message) 0; }; class ConsoleLogger : public LogStrategy { void log(const string msg) override { cout msg endl; } }; class FileLogger : public LogStrategy { void log(const string msg) override { ofstream file(log.txt, ios::app); file msg endl; } }; class CompositeLogger : public LogStrategy { vectorunique_ptrLogStrategy loggers; public: void addLogger(unique_ptrLogStrategy logger) { loggers.push_back(move(logger)); } void log(const string msg) override { for(auto l : loggers) { l-log(msg); } } };4.2 策略工厂模式结合工厂模式创建策略对象class StrategyFactory { public: static unique_ptrSortingStrategy create(const string type) { if(type quick) { return make_uniqueQuickSort(); } if(type merge) { return make_uniqueMergeSort(); } throw invalid_argument(Unknown strategy type); } }; // 使用方式 auto sorter Sorter(StrategyFactory::create(quick));4.3 策略缓存机制对昂贵策略对象实施缓存class StrategyCache { unordered_mapstring, unique_ptrSortingStrategy cache; public: SortingStrategy* get(const string type) { auto it cache.find(type); if(it cache.end()) { it cache.emplace(type, StrategyFactory::create(type)).first; } return it-second.get(); } };4.4 策略参数化配置通过配置文件动态加载策略{ sorting_strategy: quick, rendering_strategy: vulkan }class ConfigLoader { public: static unique_ptrSortingStrategy loadSortingStrategy() { auto config loadConfigFile(); return StrategyFactory::create(config[sorting_strategy]); } };5. 策略模式的性能优化5.1 避免虚函数开销对于性能敏感场景可以使用CRTP模式templatetypename T class SortingStrategy { public: void sort(vectorint data) { static_castT*(this)-doSort(data); } }; class QuickSort : public SortingStrategyQuickSort { public: void doSort(vectorint data) { // 快速排序实现 } }; templatetypename Strategy class Sorter { Strategy strategy; public: void executeSort(vectorint data) { strategy.sort(data); } };5.2 策略对象池复用策略对象减少内存分配class StrategyPool { vectorunique_ptrSortingStrategy pool; public: SortingStrategy* acquire() { if(pool.empty()) { return new QuickSort(); } auto ptr move(pool.back()); pool.pop_back(); return ptr.release(); } void release(unique_ptrSortingStrategy s) { pool.push_back(move(s)); } };5.3 编译时策略选择使用模板在编译期确定策略templatetypename Strategy class Sorter { Strategy strategy; public: void executeSort(vectorint data) { strategy.sort(data); } }; // 使用方式 SorterQuickSort sorter; sorter.executeSort(data);6. 策略模式的最佳实践6.1 何时使用策略模式策略模式特别适用于以下场景一个系统需要在多种算法中选择一种需要避免使用多重条件转移语句算法需要自由切换的场景算法实现可能被其他系统复用6.2 策略模式的优势符合开闭原则新增策略无需修改现有代码避免条件语句用多态代替条件判断算法复用策略对象可以在不同上下文中复用运行时灵活性策略可以在运行时动态切换6.3 策略模式的局限性客户端必须了解不同策略的区别策略对象会增加系统对象数量通信开销策略与上下文可能需要交换数据经验之谈当策略超过5个时考虑引入工厂模式或配置机制来管理策略对象的创建。7. 策略模式与其他模式的关系7.1 策略模式 vs 状态模式两者类图相似但意图不同策略模式客户端主动选择算法状态模式状态转换由内部条件触发7.2 策略模式 vs 模板方法模式都是封装算法但策略模式对象组合运行时绑定模板方法类继承编译时确定7.3 策略模式 vs 命令模式命令模式强调动作的执行和撤销而策略模式专注于算法的替换。8. 实际项目中的策略模式应用8.1 跨平台开发中的策略应用处理不同平台的系统API差异class FileDialogStrategy { public: virtual string openFile() 0; }; class WindowsFileDialog : public FileDialogStrategy { string openFile() override { // Windows系统API调用 } }; class MacFileDialog : public FileDialogStrategy { string openFile() override { // Mac系统API调用 } }; class FileDialog { unique_ptrFileDialogStrategy strategy; public: FileDialog() { #ifdef _WIN32 strategy make_uniqueWindowsFileDialog(); #elif __APPLE__ strategy make_uniqueMacFileDialog(); #endif } string open() { return strategy-openFile(); } };8.2 网络通信中的策略模式处理不同的网络协议class ProtocolStrategy { public: virtual void send(const Packet packet) 0; }; class TCPProtocol : public ProtocolStrategy { void send(const Packet packet) override { // TCP实现 } }; class UDPProtocol : public ProtocolStrategy { void send(const Packet packet) override { // UDP实现 } }; class NetworkManager { unique_ptrProtocolStrategy protocol; public: void setProtocol(unique_ptrProtocolStrategy p) { protocol move(p); } void sendData(const Packet packet) { protocol-send(packet); } };8.3 数据库访问策略支持多种数据库后端class DatabaseStrategy { public: virtual vectorRecord query(const string sql) 0; }; class MySQLStrategy : public DatabaseStrategy { vectorRecord query(const string sql) override { // MySQL查询实现 } }; class PostgreSQLStrategy : public DatabaseStrategy { vectorRecord query(const string sql) override { // PostgreSQL查询实现 } }; class DAL { unique_ptrDatabaseStrategy db; public: void setDatabase(unique_ptrDatabaseStrategy d) { db move(d); } vectorRecord executeQuery(const string sql) { return db-query(sql); } };9. 策略模式的测试策略9.1 单元测试策略实现测试具体策略实现TEST(QuickSortTest, SortsNumbersCorrectly) { vectorint data {3,1,4,2}; QuickSort strategy; strategy.sort(data); ASSERT_EQ(vectorint{1,2,3,4}, data); }9.2 模拟策略测试上下文使用模拟对象测试上下文class MockStrategy : public SortingStrategy { public: MOCK_METHOD(void, sort, (vectorint), (override)); }; TEST(SorterTest, DelegatesToStrategy) { MockStrategy mock; vectorint testData; EXPECT_CALL(mock, sort(_)).Times(1); Sorter sorter(make_uniqueMockStrategy(mock)); sorter.executeSort(testData); }9.3 策略切换测试验证策略切换行为TEST(SorterTest, SwitchesStrategies) { vectorint data; auto quick make_uniqueQuickSort(); auto merge make_uniqueMergeSort(); Sorter sorter(move(quick)); sorter.setStrategy(move(merge)); sorter.executeSort(data); // 验证使用归并排序 }10. 策略模式的常见误用与规避10.1 策略膨胀问题当策略类过多时会导致系统复杂化。解决方案使用策略工厂统一管理合并相似策略引入策略层次结构10.2 上下文过载问题上下文类承担太多与策略无关的职责。应该保持上下文精简将与策略无关的逻辑移到其他类遵循单一职责原则10.3 策略通信问题策略之间需要通信时通过上下文共享状态使用中介者模式避免策略直接相互依赖10.4 过度设计陷阱不是所有算法变化都需要策略模式简单条件判断足够时不要用策略算法很少变化时可能不需要权衡模式引入的复杂度实际经验在大型长期维护的项目中即使当前只有两种算法如果预计将来会扩展也应该考虑使用策略模式。
返回列表