策略模式:灵活切换算法的设计之道,Photoshop - Photoshop 工具栏(2)矩形框选工具。
策略模式的核心思想策略模式通过定义一系列算法族将每个算法封装成独立类使它们可以互相替换。该模式让算法的变化独立于使用算法的客户端符合开闭原则。模式结构Context上下文持有一个策略对象的引用通过接口调用具体策略。Strategy抽象策略声明策略的公共接口通常为抽象类或纯虚函数。ConcreteStrategy具体策略实现抽象策略的具体算法。// 抽象策略类 class Strategy { public: virtual void execute() const 0; virtual ~Strategy() default; }; // 具体策略A class ConcreteStrategyA : public Strategy { public: void execute() const override { std::cout Executing Strategy A std::endl; } }; // 具体策略B class ConcreteStrategyB : public Strategy { public: void execute() const override { std::cout Executing Strategy B std::endl; } }; // 上下文类 class Context { private: Strategy* strategy; public: Context(Strategy* s) : strategy(s) {} void setStrategy(Strategy* s) { strategy s; } void executeStrategy() const { strategy-execute(); } };动态切换策略策略模式允许运行时动态切换算法通过Context::setStrategy()实现灵活替换Context context(new ConcreteStrategyA()); context.executeStrategy(); // 输出: Executing Strategy A context.setStrategy(new ConcreteStrategyB()); context.executeStrategy(); // 输出: Executing Strategy B应用场景需要多种算法变体且后续可能扩展新算法。避免使用多重条件语句如if-else或switch-case维护不同行为。算法需要独立于客户端逻辑变化例如支付方式、排序算法等。优缺点分析优点符合单一职责原则每个策略类负责一个具体算法。符合开闭原则新增策略无需修改上下文代码。消除条件分支通过多态替代硬编码的条件逻辑。缺点客户端必须了解所有策略的差异以选择合适实现。策略类数量增多可能导致代码膨胀可通过工厂模式优化。实际案例排序算法选择class SortStrategy { public: virtual void sort(std::vectorint data) const 0; }; class QuickSort : public SortStrategy { public: void sort(std::vectorint data) const override { std::sort(data.begin(), data.end()); // 简化为标准库快速排序 std::cout Sorted via QuickSort std::endl; } }; class MergeSort : public SortStrategy { public: void sort(std::vectorint data) const override { // 模拟归并排序实现 std::stable_sort(data.begin(), data.end()); std::cout Sorted via MergeSort std::endl; } }; // 客户端调用 std::vectorint data {5, 2, 7, 1}; Context sorter(new QuickSort()); sorter.executeStrategy(); // 使用快速排序与工厂模式结合通过工厂类封装策略对象的创建逻辑进一步解耦客户端与具体策略class StrategyFactory { public: static Strategy* createStrategy(const std::string type) { if (type A) return new ConcreteStrategyA(); if (type B) return new ConcreteStrategyB(); return nullptr; } };https://github.com/miket-make/5lg_rkx2https://github.com/miket-make/5lg_rkx2/blob/main/README.mdhttps://raw.githubusercontent.com/miket-make/5lg_rkx2/main/README.mdhttps://github.com/pjongfreemen/wt9_05kahttps://github.com/pjongfreemen/wt9_05ka/blob/main/README.md