借鉴:https://blog.csdn.net/Xiluo_pro/article/details/157728687
策略模式(Strategy Pattern) 是一种行为型设计模式。
策略模式的主要目的是通过封装算法和动态切换策略,实现代码的灵活性和可维护性。
一、模式动机
策略模式旨在解决以下问题:
- 避免条件分支冗余
替代if-else或switch-case判断,通过多态动态选择算法,减少代码耦合。 - 支持算法动态切换
运行时根据需求更换具体策略(如支付方式、排序规则),无需修改上下文类代码。 - 符合开闭原则
新增策略时只需扩展具体策略类,无需修改现有代码,降低维护成本。
cpp
void func(int tpye){
if (type == A) { ... }
else if (type == B) { ... }
else if (type == C) { ... }
}
/*
说明:
算法逻辑与业务逻辑耦合严重
新增一种算法需要修改原有代码
违反 开闭原则(OCP)
*/
👉 策略模式:
把不同算法抽象成"策略对象",由外部决定使用哪一种。
二、关键实现机制
策略模式包含 3 个核心角色:
-
Strategy(抽象策略)
定义算法接口
-
ConcreteStrategy(具体策略)
实现具体算法
-
Context(上下文)
持有策略对象,调用其算法
关键实现机制(策略模式=多态+上下文环境类)
- 多态
通过抽象策略接口(如PaymentStrategy)统一调用方法,具体实现(如AlipayStrategy)在运行时动态绑定。 - 上下文环境类
封装策略切换逻辑(如OrderProcessor.setStrategy()),客户端只需与上下文交互,无需直接依赖具体策略。
有同学会问,多态就够了呀为什么还需要上下文环境类?解答如下:
-
上下文类的核心作用
上下文类(Context)是策略模式的关键组件,它负责:- 解耦客户端与策略实现:客户端只需选择策略,无需直接调用具体算法。
- 封装复杂逻辑:如线程池的拒绝策略、资源管理等,由上下文统一处理。
- 提供统一接口:客户端无论使用何种策略,调用方式始终一致。
-
不使用上下文类的后果
- 耦合度增加:客户端直接依赖具体策略类,修改算法时需同时修改客户端代码(违反开闭原则)。
- 代码重复 :多个客户端需重复实现策略调用逻辑(如
if-else分支)。 - 可扩展性降低:新增策略时需遍历所有客户端代码进行修改。
-
何时可以省略上下文类
仅当满足以下条件时,可考虑省略上下文类:
- 算法极其简单 :如加减乘除,可直接用多态或函数式编程(Java 8+的
Lambda)。 - 无复杂逻辑:策略调用无需额外处理(如资源管理、状态同步)。
- 客户端数量少:且策略变化频率低,硬编码成本可接受。
- 算法极其简单 :如加减乘除,可直接用多态或函数式编程(Java 8+的
三、C++ 示例
cpp
//抽象策略
class SortStrategy {
public:
virtual ~SortStrategy() {}
virtual void sort(std::vector<int>& data) = 0;
};
//具体策略
class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// 冒泡排序
}
};
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) override {
// 快速排序
}
};
//上下文
class SortContext {
public:
void setStrategy(SortStrategy* s) {
strategy = s;
}
void execute(std::vector<int>& data) {
if (strategy)
strategy->sort(data);
}
private:
SortStrategy* strategy = nullptr;
};
int main() {
std::vector<int> v = {5, 2, 8, 1};
BubbleSort bubble;
QuickSort quick;
SortContext ctx;
ctx.setStrategy(&bubble);
ctx.execute(v); // 使用冒泡排序
ctx.setStrategy(&quick);
ctx.execute(v); // 切换为快速排序
}
四、典型应用场景
-
多种算法可互换
-
排序方式
-
压缩算法(zip、rar、7z)
-
加密算法(AES、RSA、MD5)
-
-
避免大量 if-else / switch-case
-
运行时动态切换算法
都很适合用策略模式。