策略模式详解(附带C++实现)
封装是面向对象编程的基石之一,它不仅保护了数据的安全性,也使得代码更易于管理和扩展。在设计模式中,封装行为的思想被运用于多种模式中,其中就包括策略模式。
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换使用。这种模式让算法的变更独立于使用算法的客户端。
策略模式的应用场景和优势如下:
例如,在一个电子商务系统中,不同类型的用户或购买的不同商品类型可能会应用不同的折扣计算策略。通过策略模式,系统可以在不修改现有代码的情况下引入新的折扣算法,或者改变现有算法,以适应市场的变化。
封装不仅仅是数据保护的工具,它也是一种功能强大的设计策略,用于提高软件系统的可维护性和可扩展性。策略模式通过封装行为和算法,允许开发者构建出更加灵活和具有更强适应性的应用。
该模式的核心设计准则包括:
通过应用这些设计准则,策略模式可以有效地帮助开发者管理和扩展代码。
策略模式的基本流程如下图所示:

图 1 策略模式
在 C++ 中实现策略模式时,通常会定义一个策略接口,以及一些实现这个接口的具体策略类。上下文类会使用一个策略接口的引用或指针,以调用具体策略实现的方法。
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换使用。这种模式让算法的变更独立于使用算法的客户端。
策略模式的应用场景和优势如下:
- 优化选择:当有多种算法适用于某个特定的任务时,策略模式允许在运行时选择最适合的方法;
- 动态替换:策略模式支持根据不同的情境动态地替换方法的实现,提高了应用的灵活性。
例如,在一个电子商务系统中,不同类型的用户或购买的不同商品类型可能会应用不同的折扣计算策略。通过策略模式,系统可以在不修改现有代码的情况下引入新的折扣算法,或者改变现有算法,以适应市场的变化。
封装不仅仅是数据保护的工具,它也是一种功能强大的设计策略,用于提高软件系统的可维护性和可扩展性。策略模式通过封装行为和算法,允许开发者构建出更加灵活和具有更强适应性的应用。
策略模式的设计准则
策略模式的关键在于定义一系列算法,把它们一一封装起来,并使它们可相互替换。该模式的核心设计准则包括:
- 定义算法族:策略模式要求识别出应用中涉及的相关算法,并将每个算法封装到具有共同接口的独立类中;
- 运行时策略选择:策略模式允许在运行时选择使用哪种算法。为此,策略对象通常从上下文对象中分离出来,并通过同一策略接口进行交互;
- 互换性:策略模式的设计应确保所有策略类实现相同的接口。这种一致性使得策略之间可以自由替换,而不会影响使用策略的客户端;
- 简化上下文:策略模式应简化上下文类的责任,上下文不应该包含策略决策逻辑,而只需要维护与策略对象的关联。
通过应用这些设计准则,策略模式可以有效地帮助开发者管理和扩展代码。
策略模式的角色
策略模式通常包括 3 个主要角色:- 上下文:维护一个对策略对象的引用,可以定义一个接口来让策略访问它的数据;
- 策略接口:定义所有支持的算法的公共接口;
- 具体策略:实现策略接口的具体算法。
策略模式的基本流程如下图所示:

图 1 策略模式
在 C++ 中实现策略模式时,通常会定义一个策略接口,以及一些实现这个接口的具体策略类。上下文类会使用一个策略接口的引用或指针,以调用具体策略实现的方法。
C++实现策略模式
以下是一个简单的例子,展示如何在 C++ 中应用策略模式:#include <iostream> #include <memory> // Strategy Interface: 定义所有支持的算法的公共接口 class Strategy { public: virtual ~Strategy() {} virtual void execute() const = 0; }; // ConcreteStrategyA: 实现策略接口的具体算法A class ConcreteStrategyA : public Strategy { public: void execute() const override { std::cout << "Executing strategy A." << std::endl; } }; // ConcreteStrategyB: 实现策略接口的具体算法B class ConcreteStrategyB : public Strategy { public: void execute() const override { std::cout << "Executing strategy B." << std::endl; } }; // Context: 维护一个对策略对象的引用 class Context { private: std::unique_ptr<Strategy> strategy; // 使用智能指针管理策略对象 public: Context(Strategy* strategy = nullptr) : strategy(strategy) {} ~Context() {} // 允许替换当前的策略对象 void setStrategy(Strategy* newStrategy) { strategy.reset(newStrategy); } // 执行策略 void executeStrategy() const { if (strategy) { strategy->execute(); } } }; int main() { Context context; // 使用动态分配的策略对象 context.setStrategy(new ConcreteStrategyA()); context.executeStrategy(); // 切换到策略B context.setStrategy(new ConcreteStrategyB()); context.executeStrategy(); return 0; }在上述代码中:
- Strategy:这是一个策略接口,所有的策略类都必须实现这个接口;
- ConcreteStrategyA 和 ConcreteStrategyB:是实现了 Strategy 接口的具体策略类,每个类提供了不同的算法实现;
- Context:这是使用策略的类。它包含了一个指向策略对象的指针,可以通过 setStrategy 方法来改变所使用的具体策略。executeStrategy 方法用于调用当前策略的执行方法。