1. 策略模式在C++中的核心价值
策略模式(Strategy Pattern)是我在大型C++项目中频繁使用的设计模式之一。它通过定义算法族并封装每个算法,使它们可以相互替换,这种模式让算法的变化独立于使用算法的客户。在游戏开发、金融计算等需要频繁切换算法的场景中,策略模式能显著提升代码的灵活性和可维护性。
以游戏开发为例,当我们需要为角色实现不同的攻击行为时,传统做法可能会使用复杂的条件判断语句。而采用策略模式后,我们可以将每种攻击算法封装成独立类,运行时动态切换。这不仅消除了庞大的if-else结构,还使得新增攻击类型变得异常简单——只需添加新的策略类而无需修改现有代码。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 策略模式的经典实现方案
2.1 基础类结构设计
标准的策略模式包含三个核心组件:
- Context(上下文):维护对策略对象的引用
- Strategy(抽象策略):定义算法接口
- ConcreteStrategy(具体策略):实现具体算法
cpp复制// 抽象策略接口
class SortingStrategy {
public:
virtual void sort(vector<int>& data) = 0;
virtual ~SortingStrategy() = default;
};
// 具体策略:快速排序
class QuickSort : public SortingStrategy {
public:
void sort(vector<int>& data) override {
cout << "Sorting using QuickSort" << endl;
// 实际快速排序实现
}
};
// 具体策略:归并排序
class MergeSort : public SortingStrategy {
public:
void sort(vector<int>& data) override {
cout << "Sorting using MergeSort" << endl;
// 实际归并排序实现
}
};
// 上下文类
class Sorter {
private:
SortingStrategy* strategy;
public:
explicit Sorter(SortingStrategy* strategy) : strategy(strategy) {}
void setStrategy(SortingStrategy* newStrategy) {
strategy = newStrategy;
}
void executeSort(vector<int>& data) {
strategy->sort(data);
}
};
2.2 现代C++的改进实现
C++11之后的版本提供了更优雅的实现方式:
cpp复制// 使用function和lambda替代传统接口
class ModernSorter {
private:
function<void(vector<int>&)> strategy;
public:
explicit ModernSorter(function<void(vector<int>&)> strat)
: strategy(move(strat)) {}
void setStrategy(function<void(vector<int>&)> newStrat) {
strategy = move(newStrat);
}
void execute(vector<int>& data) {
strategy(data);
}
};
// 使用示例
auto quickSort = [](vector<int>& data) {
cout << "Modern QuickSort" << endl;
};
ModernSorter sorter(quickSort);
3. 实战应用:游戏技能系统设计
3.1 技能策略建模
在ARPG游戏中,不同职业的技能释放逻辑差异很大:
cpp复制class SkillStrategy {
public:
virtual void execute() = 0;
virtual ~SkillStrategy() = default;
};
class WarriorSkill : public SkillStrategy {
public:
void execute() override {
cout << "战士技能:旋风斩!" << endl;
}
};
class MageSkill : public SkillStrategy {
public:
void execute() override {
cout << "法师技能:火球术!" << endl;
}
};
class Character {
unique_ptr<SkillStrategy> skill;
public:
void setSkill(unique_ptr<SkillStrategy> newSkill) {
skill = move(newSkill);
}
void useSkill() {
if(skill) skill->execute();
}
};
3.2 动态切换策略
通过策略模式,我们可以实现战斗中的实时技能切换:
cpp复制Character hero;
hero.setSkill(make_unique<WarriorSkill>());
hero.useSkill(); // 输出:战士技能:旋风斩!
// 获得法师技能书后切换
hero.setSkill(make_unique<MageSkill>());
hero.useSkill(); // 输出:法师技能:火球术!
4. 性能优化与设计考量
4.1 内存管理策略
在性能敏感场景中,可以考虑以下优化方案:
- 对象池技术:预先创建策略对象池,避免运行时频繁分配
- 小对象优化:对于小型策略对象,使用局部存储而非堆分配
- 无继承实现:C++20的concept可以替代传统多态
cpp复制// 对象池示例
class StrategyPool {
static unordered_map<size_t, vector<unique_ptr<SortingStrategy>>> pool;
public:
template<typename T>
static T* acquire() {
auto& list = pool[typeid(T).hash_code()];
if(list.empty()) {
return new T();
}
auto ptr = list.back().release();
list.pop_back();
return static_cast<T*>(ptr);
}
template<typename T>
static void release(T* strategy) {
pool[typeid(T).hash_code()].emplace_back(strategy);
}
};
4.2 线程安全实现
多线程环境下使用策略模式需要注意:
cpp复制class ThreadSafeSorter {
mutex mtx;
unique_ptr<SortingStrategy> strategy;
public:
void setStrategy(unique_ptr<SortingStrategy> newStrategy) {
lock_guard<mutex> lock(mtx);
strategy = move(newStrategy);
}
void execute(vector<int>& data) {
lock_guard<mutex> lock(mtx);
if(strategy) strategy->sort(data);
}
};
5. 实际项目中的经验总结
5.1 策略模式的优势
- 开闭原则:新增策略无需修改现有代码
- 消除条件语句:替代复杂的if-else或switch-case结构
- 运行时灵活性:动态切换算法实现
- 可测试性:每个策略可以独立测试
5.2 常见陷阱与解决方案
-
策略对象生命周期管理
- 问题:上下文类持有策略指针可能导致内存泄漏
- 方案:使用智能指针(unique_ptr/shared_ptr)
-
策略接口膨胀
- 问题:策略接口方法过多导致实现困难
- 方案:将大接口拆分为多个小策略接口
-
性能开销
- 问题:虚函数调用带来的间接成本
- 方案:对性能关键路径考虑静态策略或CRTP模式
cpp复制// CRTP实现示例
template<typename Derived>
class SortingStrategyCRTP {
public:
void sort(vector<int>& data) {
static_cast<Derived*>(this)->sortImpl(data);
}
};
class QuickSortCRTP : public SortingStrategyCRTP<QuickSortCRTP> {
friend class SortingStrategyCRTP<QuickSortCRTP>;
void sortImpl(vector<int>& data) {
cout << "CRTP QuickSort" << endl;
}
};
6. 与其他设计模式的协同应用
6.1 策略+工厂模式
通过工厂方法创建策略对象:
cpp复制class StrategyFactory {
public:
static unique_ptr<SortingStrategy> create(const string& type) {
if(type == "quick") return make_unique<QuickSort>();
if(type == "merge") return make_unique<MergeSort>();
throw invalid_argument("Unknown strategy type");
}
};
6.2 策略+装饰器模式
动态添加策略的附加功能:
cpp复制class LoggingDecorator : public SortingStrategy {
unique_ptr<SortingStrategy> wrapped;
public:
explicit LoggingDecorator(unique_ptr<SortingStrategy> strategy)
: wrapped(move(strategy)) {}
void sort(vector<int>& data) override {
auto start = chrono::high_resolution_clock::now();
wrapped->sort(data);
auto end = chrono::high_resolution_clock::now();
cout << "Sorting took "
<< chrono::duration_cast<chrono::microseconds>(end-start).count()
<< "μs" << endl;
}
};
7. 现代C++中的进阶技巧
7.1 使用std::variant实现策略模式
C++17引入的variant可以替代传统多态:
cpp复制using StrategyVariant = variant<QuickSort, MergeSort>;
class VariantSorter {
StrategyVariant strategy;
public:
explicit VariantSorter(StrategyVariant s) : strategy(move(s)) {}
void execute(vector<int>& data) {
visit([&data](auto&& s) { s.sort(data); }, strategy);
}
};
7.2 策略模式与并发编程
结合并行算法实现高性能策略:
cpp复制class ParallelQuickSort : public SortingStrategy {
public:
void sort(vector<int>& data) override {
cout << "Parallel QuickSort" << endl;
// 使用并行算法实现
}
};
// 使用时根据CPU核心数选择策略
auto chooseStrategy() -> unique_ptr<SortingStrategy> {
unsigned cores = thread::hardware_concurrency();
return cores > 4 ? make_unique<ParallelQuickSort>()
: make_unique<QuickSort>();
}
在实际项目中,策略模式的价值往往在系统演进过程中逐渐显现。当需求变更要求增加新的算法变体时,良好的策略模式实现可以让扩展变得轻松自然。我在一个交易引擎项目中,通过策略模式将不同的价格计算算法解耦,使得后续新增定价模型的时间从原来的2-3天缩短到2-3小时。
