解释
Strategy 模式和 Template 模式要解决的问题是相同(类似)的,都是为了给业务逻辑(算法)具体实现和抽象接口之间的解耦。Strategy 模式将逻辑(算法)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给组合对象实现。
应用场景示例:
数据导出格式选择假设需要实现一个数据导出工具,支持多种格式(CSV、XML、JSON)。若不用策略模式,会在导出逻辑中频繁出现条件分支,导致代码臃肿且难以扩展。
不使用策略模式的问题代码
class DataExporter {
public:void exportData(const std::string& format) {if (format == "CSV") {// CSV导出逻辑(约20行代码)std::cout << "Exporting data as CSV..." << std::endl;} else if (format == "XML") {// XML导出逻辑(约30行代码)std::cout << "Exporting data as XML..." << std::endl;} else if (format == "JSON") {// JSON导出逻辑(约25行代码)std::cout << "Exporting data as JSON..." << std::endl;}// 每新增一个格式都要修改此处}
};
使用策略模式的解决方案
// 策略接口
class ExportStrategy {
public:virtual ~ExportStrategy() = default;virtual void executeExport() = 0;
};// 具体策略
class CsvExport : public ExportStrategy {
public:void executeExport() override {std::cout << "Exporting data as CSV..." << std::endl;}
};class XmlExport : public ExportStrategy {
public:void executeExport() override {std::cout << "Exporting data as XML..." << std::endl;}
};class JsonExport : public ExportStrategy {
public:void executeExport() override {std::cout << "Exporting data as JSON..." << std::endl;}
};// 上下文类
class ExportContext {
private:ExportStrategy* strategy_;
public:void setStrategy(ExportStrategy* strategy) {strategy_ = strategy;}void performExport() {if (strategy_) {strategy_->executeExport();} else {std::cout << "No export strategy selected!" << std::endl;}}
};
关键对比分析
维度 | 无策略模式 | 使用策略模式 |
---|---|---|
扩展性 | 新增格式需修改原有类 | 只需新增策略类,符合开闭原则 |
可维护性 | 200行巨型方法难维护 | 每个策略独立维护(20-30行/类) |
测试难度 | 需覆盖所有条件分支 | 可单独测试每个策略 |
代码复用 | 相似逻辑无法复用 | 可跨项目复用导出策略 |
运行时灵活性 | 需重启修改代码 | 动态切换导出策略(如根据配置文件) |
典型应用场景
- 文件压缩工具:支持ZIP/RAR/7Z等算法
- 导航系统:实时切换最短路径/避开收费/避开高速等路线策略
- 游戏AI:不同难度级别的敌人行为策略
- 数据校验:多种校验规则(邮箱/手机号/身份证)的动态切换
何时不建议使用?
- 策略数量极少(<3种)且确定不会扩展
- 策略之间存在大量共享状态导致解耦困难
- 算法需要访问对象内部私有状态(可能破坏封装)
通过这种设计,系统核心复杂度从O(n)(每次新增策略都要修改核心类)降为O(1),特别适合需要频繁扩展业务场景的中间件系统或框架设计。