策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,将每个算法封装到不同的类中,并且使它们可以相互替换。策略模式允许客户端代码选择算法的实现,而不是将算法的选择硬编码在客户端代码中。
? 策略模式中,首先定义一个抽象基类或接口,它代表着所有可能被应用的算法的共性。然后我们编写具体的子类实现这个接口,并实现各自的算法函数。最后,我们编写一个环境类或上下文类,该类持有一个指向抽象基类或接口类型的指针,客户端可以传递不同的具体算法对象给环境类或上下文类,从而动态地改变其行为。
以下是策略模式的关键组成部分:
策略的抽象基类或者接口,该类定义了所有可能被应用的算法的共性。定义抽象的函数算法让继承的子类实现。
// 策略接口
class Strategy
{
public:
virtual void execute() const = 0;
};
它们继承自 Strategy 类,并实现了各自的算法函数,即函数的具体功能的实现。
// 具体策略类 A
class ConcreteStrategyA : public Strategy
{
public:
void execute() const override
{
std::cout << "执行策略 A" << std::endl;
}
};
// 具体策略类 B
class ConcreteStrategyB : public Strategy
{
public:
void execute() const override
{
std::cout << "执行策略 B" << std::endl;
}
};
维持一个对策略对象的引用,可以在运行时切换不同的策略。该类持有一个指向抽象基类或接口类型的指针,客户端可以传递不同的具体算法对象给环境类,从而动态地改变其行为(多态)。上下文类有一个executeStrategy()
方法,该方法会调用持有的策略对象的 execute()
函数来执行具体算法。
// 上下文类
class Context
{
private:
Strategy* strategy;
public:
Context(Strategy* strategy) : strategy(strategy) {}
void setStrategy(Strategy* newStrategy)
{
strategy = newStrategy;
}
void executeStrategy() const
{
strategy->execute();
}
};
使用策略模式的主要优势在于,它允许在运行时选择算法,而不是在编译时进行硬编码。这使得系统更加灵活,易于扩展,同时也符合开闭原则。
main()
{
ConcreteStrategyA strategyA;
ConcreteStrategyB strategyB;
Context context(&strategyA);
context.executeStrategy(); // 执行策略 A
context.setStrategy(&strategyB);
context.executeStrategy(); // 执行策略 B
return 0;
}
上述例子中,Context
类可以在运行时切换不同的策略,而不需要修改客户端代码。这符合策略模式的核心思想。
? 策略模式是对象行为型模式 ,它关注行为和算法的封装 。其优势在于可以将算法的实现和使用分离,它定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换。方便客户端动态地替换策略对象,并且可以避免使用多重条件语句来选择不同的算法实现。使得算法可独立于使用它的客户而变化。即可以通过直接调用基类的方式完成赋值。