策略模式(Strategy Pattern)是一种行为设计模式,其核心思想是将算法的定义与使用分离,使算法可以独立于客户端进行变化。它通过定义一系列算法,将每个算法封装到独立的类中,并使它们可以互相替换,从而让算法的变化不会影响到使用算法的客户端。
介绍
策略模式的核心组件
-
策略接口(Strategy Interface) :
定义所有具体策略必须实现的公共方法,通常是一个抽象类或接口。例如,在排序场景中,策略接口可能定义
sort()
方法。 -
具体策略(Concrete Strategies) :
实现策略接口的具体算法类。例如:
BubbleSort
、QuickSort
、MergeSort
等。 -
上下文(Context) :
持有一个策略接口的引用,负责根据需要动态切换具体策略。上下文不直接实现算法,而是将工作委托给策略对象。
-
客户端(Client) :
负责创建具体策略并将其注入到上下文中,控制策略的选择逻辑。
策略模式的特点
-
可替换性 :
客户端可以在运行时动态切换策略,无需修改上下文代码。
-
开闭原则 :
新增策略只需实现接口,无需修改现有代码,符合"对扩展开放,对修改关闭"的原则。
-
解耦算法 :
算法的实现细节被封装在具体策略中,客户端无需关心其内部逻辑。
-
消除条件语句 :
避免使用大量
if-else
或switch
语句来选择算法,使代码更简洁。
适用场景
- 多种算法选择:当一个问题有多种解决算法,且需要在运行时动态切换时。
- 避免条件语句 :替代大量的
if-else
或switch
语句,使代码更清晰。 - 算法封装:将算法的实现细节与使用算法的客户端代码分离。
实现
cpp
#include <iostream>
#include <memory>
#include <string>
// 策略接口:定义算法族
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(std::vector<int>& data) const = 0;
};
// 具体策略:冒泡排序
class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) const override {
std::cout << "使用冒泡排序..." << std::endl;
// 冒泡排序实现
int n = data.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (data[j] > data[j + 1]) {
std::swap(data[j], data[j + 1]);
}
}
}
}
};
// 具体策略:快速排序
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) const override {
std::cout << "使用快速排序..." << std::endl;
// 快速排序实现
quickSort(data, 0, data.size() - 1);
}
private:
void quickSort(std::vector<int>& data, int left, int right) const {
if (left < right) {
int pivotIndex = partition(data, left, right);
quickSort(data, left, pivotIndex - 1);
quickSort(data, pivotIndex + 1, right);
}
}
int partition(std::vector<int>& data, int left, int right) const {
int pivot = data[right];
int i = left - 1;
for (int j = left; j < right; ++j) {
if (data[j] <= pivot) {
++i;
std::swap(data[i], data[j]);
}
}
std::swap(data[i + 1], data[right]);
return i + 1;
}
};
// 上下文:维护一个策略引用
class Sorter {
private:
std::unique_ptr<SortStrategy> strategy;
public:
explicit Sorter(std::unique_ptr<SortStrategy> strategy)
: strategy(std::move(strategy)) {}
void setStrategy(std::unique_ptr<SortStrategy> strategy) {
this->strategy = std::move(strategy);
}
void performSort(std::vector<int>& data) const {
if (strategy) {
strategy->sort(data);
} else {
std::cout << "未设置排序策略" << std::endl;
}
}
};
// 客户端代码
int main() {
std::vector<int> data = {5, 4, 3, 2, 1};
// 使用冒泡排序
Sorter sorter(std::make_unique<BubbleSort>());
sorter.performSort(data);
for (int num : data) {
std::cout << num << " ";
}
std::cout << std::endl;
// 切换为快速排序
data = {5, 4, 3, 2, 1};
sorter.setStrategy(std::make_unique<QuickSort>());
sorter.performSort(data);
for (int num : data) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
应用场景
- 排序算法切换:根据数据规模选择冒泡排序、快速排序等。
- 支付方式:电商系统中支持支付宝、微信、银行卡等多种支付方式。
- 压缩算法:文件压缩工具支持ZIP、RAR、7Z等不同压缩算法。
- 游戏AI:不同难度的敌人使用不同的行为策略。
- 加密算法:安全系统中动态选择加密方式(MD5、SHA-256等)。
策略模式与其他模式的对比
模式 | 核心区别 |
---|---|
策略模式 | 算法的定义与使用分离,强调运行时动态切换。 |
状态模式 | 行为随内部状态变化而变化,状态转换通常由上下文触发。 |
工厂模式 | 专注于对象的创建,而不涉及对象的行为。 |
策略模式优化(注册机制和反射)
优化措施
-
策略工厂与注册机制:
StrategyFactory
使用单例模式管理策略的创建- 通过
registerStrategy
方法注册策略名称和对应的工厂函数 StrategyRegistrar
模板类用于静态注册,避免手动调用注册函数
-
反射机制:
- 使用
std::function
和 lambda 表达式实现类型擦除 - 通过字符串名称动态创建策略对象
- 静态注册确保在程序初始化时完成所有策略的注册
- 使用
-
Sorter类改进:
- 在构造函数中初始化所有策略实例
- 使用
std::unordered_map
管理策略对象 - 通过
setStrategy
方法动态切换当前使用的策略 - 所有策略对象仅创建一次,提高性能
cpp
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <unordered_map>
#include <functional>
// 策略接口
class SortStrategy {
public:
virtual ~SortStrategy() = default;
virtual void sort(std::vector<int>& data) const = 0;
};
// 具体策略:冒泡排序
class BubbleSort : public SortStrategy {
public:
void sort(std::vector<int>& data) const override {
std::cout << "使用冒泡排序..." << std::endl;
int n = data.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (data[j] > data[j + 1]) {
std::swap(data[j], data[j + 1]);
}
}
}
}
};
// 具体策略:快速排序
class QuickSort : public SortStrategy {
public:
void sort(std::vector<int>& data) const override {
std::cout << "使用快速排序..." << std::endl;
quickSort(data, 0, data.size() - 1);
}
private:
void quickSort(std::vector<int>& data, int left, int right) const {
if (left < right) {
int pivotIndex = partition(data, left, right);
quickSort(data, left, pivotIndex - 1);
quickSort(data, pivotIndex + 1, right);
}
}
int partition(std::vector<int>& data, int left, int right) const {
int pivot = data[right];
int i = left - 1;
for (int j = left; j < right; ++j) {
if (data[j] <= pivot) {
++i;
std::swap(data[i], data[j]);
}
}
std::swap(data[i + 1], data[right]);
return i + 1;
}
};
// 策略工厂:负责创建策略实例
class StrategyFactory {
public:
static StrategyFactory& getInstance() {
static StrategyFactory instance;
return instance;
}
void registerStrategy(const std::string& name, std::function<std::unique_ptr<SortStrategy>()> factory) {
factories[name] = factory;
}
std::unique_ptr<SortStrategy> createStrategy(const std::string& name) {
auto it = factories.find(name);
if (it != factories.end()) {
return it->second();
}
return nullptr;
}
private:
StrategyFactory() = default;
std::unordered_map<std::string, std::function<std::unique_ptr<SortStrategy>()>> factories;
};
// 策略注册表:静态注册策略
template<typename T>
struct StrategyRegistrar {
StrategyRegistrar(const std::string& name) {
StrategyFactory::getInstance().registerStrategy(name, []() {
return std::make_unique<T>();
});
}
};
// 上下文:维护策略并提供排序功能
class Sorter {
public:
Sorter() {
strategies["bubble"] = StrategyFactory::getInstance().createStrategy("bubble");
strategies["quick"] = StrategyFactory::getInstance().createStrategy("quick");
currentStrategy = strategies["bubble"].get();
}
void setStrategy(const std::string& name) {
auto it = strategies.find(name);
if (it != strategies.end()) {
currentStrategy = it->second.get();
} else {
std::cout << "未找到策略: " << name << std::endl;
}
}
void performSort(std::vector<int>& data) const {
if (currentStrategy) {
currentStrategy->sort(data);
} else {
std::cout << "未设置排序策略" << std::endl;
}
}
private:
std::unordered_map<std::string, std::unique_ptr<SortStrategy>> strategies;
SortStrategy* currentStrategy;
};
// 静态注册策略
static StrategyRegistrar<BubbleSort> bubbleRegistrar("bubble");
static StrategyRegistrar<QuickSort> quickRegistrar("quick");
// 客户端代码
int main() {
std::vector<int> data = {5, 4, 3, 2, 1};
Sorter sorter;
// 使用冒泡排序
sorter.setStrategy("bubble");
sorter.performSort(data);
for (int num : data) {
std::cout << num << " ";
}
std::cout << std::endl;
// 切换为快速排序
data = {5, 4, 3, 2, 1};
sorter.setStrategy("quick");
sorter.performSort(data);
for (int num : data) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
添加新策略时,只需:
-
创建新的策略类,继承自
SortStrategy
-
实现
sort
方法 -
添加静态注册语句:
cppstatic StrategyRegistrar<NewSortStrategy> newRegistrar("new");
// 无需修改 Sorter
类,完全符合开闭原则。
客户端通过字符串名称即可使用新策略,实现了对修改封闭,对扩展开放的设计目标。