什么是策略模式?一般用于什么场景?
策略模式一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使得它们可以相互替换,这样,客户端可以根据需要在运行时选择合适的算法,而不需要更改原有的代码。
很多时候,代码中有大量中有大量的if else,Switch等,可以通过使用策略模式,避免大量条件语句使用,实现算法的分离和独立变化。
代码示例:
//策略模式
#include <iostream>
#include <memory>//引入智能指针头文件// 策略接口,定义了执行策略的方法
class Strategy {
public:virtual void execute() const = 0; // execute()是纯虚函数,没有实现,要求子类必须实现这个函数// 纯虚函数是没有实现的虚函数,子类必须实现这个函数,否则子类也会变成抽象类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:std::unique_ptr<Strategy> strategy; // 使用智能指针来管理策略对象的生命周期,避免手动内存管理的麻烦// unique_ptr是C++11引入的智能指针,表示独占所有权的指针,不能被复制,只能被移动,避免了内存泄漏的问题// unique_ptr的构造函数是私有的,不能直接创建对象,只能通过std::make_unique来创建对象,对象类型是Strategy的子类//strategy是一个指向策略接口的智能指针,表示当前上下文使用的策略对象,此时strategy是一个空指针,表示没有策略对象被设置//为什么设置为私有?因为上下文类不应该直接访问策略对象的实现细节,只能通过策略接口来调用策略对象的方法// 这样可以实现策略模式的开放封闭原则,允许在不修改上下文类的情况下,添加新的策略对象,如策略A和策略B
public:void setStrategy(std::unique_ptr<Strategy> newStrategy) {//newStrategy是一个智能指针,表示新的策略对象strategy = std::move(newStrategy); // 使用std::move将newStrategy的所有权转移给strategy,避免重复创建对象}void executeStrategy() const {// 执行策略的方法,调用当前策略对象的execute()方法// const修饰符表示这个方法不会修改类的成员变量,保证了方法的安全性if (strategy) {//判断策略对象是否为空// 如果不为空,则调用策略对象的方法strategy->execute();} else {std::cout << "No strategy set" << std::endl;}}
};// 客户端
int main() {Context context; // 创建上下文对象,上下文类是策略模式的核心类,负责管理策略对象的生命周期和执行策略的方法context.setStrategy(std::make_unique<ConcreteStrategyA>());//make_unique是C++11引入的函数模板,用于创建智能指针对象,避免手动内存管理的麻烦// make_unique的参数是一个策略对象的构造函数,表示创建一个新的策略对象,并将其所有权转移给上下文对象context.executeStrategy(); // Output: Executing Strategy Acontext.setStrategy(std::make_unique<ConcreteStrategyB>());context.executeStrategy(); // Output: Executing Strategy Bsystem("pause");// 这里使用了智能指针来管理策略对象的生命周期,避免了手动内存管理的麻烦。return 0;
}