设计模式-Strategy 模式(策略)

发布于:2025-02-27 ⋅ 阅读:(9) ⋅ 点赞:(0)

解释

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行/类)
测试难度 需覆盖所有条件分支 可单独测试每个策略
代码复用 相似逻辑无法复用 可跨项目复用导出策略
运行时灵活性 需重启修改代码 动态切换导出策略(如根据配置文件)

典型应用场景

  1. 文件压缩工具:支持ZIP/RAR/7Z等算法
  2. 导航系统:实时切换最短路径/避开收费/避开高速等路线策略
  3. 游戏AI:不同难度级别的敌人行为策略
  4. 数据校验:多种校验规则(邮箱/手机号/身份证)的动态切换

何时不建议使用?

  • 策略数量极少(<3种)且确定不会扩展
  • 策略之间存在大量共享状态导致解耦困难
  • 算法需要访问对象内部私有状态(可能破坏封装)

通过这种设计,系统核心复杂度从O(n)(每次新增策略都要修改核心类)降为O(1),特别适合需要频繁扩展业务场景的中间件系统或框架设计。