Bootstrap

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


类图: 策略设计模式类图

一.什么是策略设计模式?

策略设计模式(Strategy Pattern)是一种行为型设计模式,定义了一系列算法,并将每种算法封装起来,使得它们可以互换使用。通过这种模式,算法的变化不会影响使用算法的上下文代码。

二.策略模式的特点

  1. 封装算法:将每种算法封装为独立的类,使得算法可以独立于使用它的客户端变化。
  2. 开放/关闭原则:通过新增策略类扩展新算法,而无需修改已有代码。
  3. 互换性:不同的策略实现可以互相替代,而不影响上下文。

三.策略模式的结构

  1. Context(上下文类)
    • 持有一个 Strategy 对象的引用。
    • 定义了操作接口,客户端通过上下文调用具体策略的方法。
  2. Strategy(抽象策略类)
    • 定义所有具体策略的公共接口。
    • 每个策略类都实现这个接口,提供不同的算法实现。
  3. ConcreteStrategy(具体策略类)
    • 实现了抽象策略接口中的方法。
    • 封装具体的算法逻辑。
      在这里插入图片描述

四.策略模式的应用场景

  1. 需要动态选择算法或行为的场景。
  2. 算法具有多种实现方式,需要灵活切换。
  3. 避免大量条件语句,使代码更加清晰。

五.策略模式的优缺点

  • 优点:
    • 算法的独立性:每个策略类实现了独立的算法,便于维护和扩展。
    • 代码清晰:避免了条件分支语句,提高了代码的可读性。
    • 灵活性:通过上下文动态选择不同的策略实现。
  • 缺点:
    • 类数量增加:每种算法需要对应一个策略类,可能导致类数量较多。
    • 上下文与策略耦合:上下文需要了解所有策略类的定义,增加了代码的复杂性。

六.策略模式的C++实现

#include <iostream>
#include <memory>
using namespace std;

// 抽象策略类
class Strategy {
public:
    virtual void AlgorithmInterface() const = 0; // 定义算法接口
    virtual ~Strategy() = default;
};

// 具体策略A
class ConcreteStrategyA : public Strategy {
public:
    void AlgorithmInterface() const override {
        cout << "Executing Algorithm A" << endl;
    }
};

// 具体策略B
class ConcreteStrategyB : public Strategy {
public:
    void AlgorithmInterface() const override {
        cout << "Executing Algorithm B" << endl;
    }
};

// 具体策略C
class ConcreteStrategyC : public Strategy {
public:
    void AlgorithmInterface() const override {
        cout << "Executing Algorithm C" << endl;
    }
};

// 上下文类
class Context {
private:
    unique_ptr<Strategy> strategy; // 持有策略对象
public:
    explicit Context(unique_ptr<Strategy> strategy) : strategy(move(strategy)) {}

    void SetStrategy(unique_ptr<Strategy> newStrategy) {
        strategy = move(newStrategy);
    }

    void ContextInterface() const {
        cout << "Context is using strategy: ";
        strategy->AlgorithmInterface(); // 调用具体策略的方法
    }
};

// 客户端代码
int main() {
    // 使用策略A
    unique_ptr<Context> context = make_unique<Context>(make_unique<ConcreteStrategyA>());
    context->ContextInterface();

    // 切换到策略B
    context->SetStrategy(make_unique<ConcreteStrategyB>());
    context->ContextInterface();

    // 切换到策略C
    context->SetStrategy(make_unique<ConcreteStrategyC>());
    context->ContextInterface();

    return 0;
}

七.策略模式的JAVA实现

// 抽象策略类
interface Strategy {
    void algorithmInterface(); // 定义算法接口
}

// 具体策略A
class ConcreteStrategyA implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("Executing Algorithm A");
    }
}

// 具体策略B
class ConcreteStrategyB implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("Executing Algorithm B");
    }
}

// 具体策略C
class ConcreteStrategyC implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("Executing Algorithm C");
    }
}

// 上下文类
class Context {
    private Strategy strategy; // 持有策略对象

    // 设置初始策略
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    // 切换策略
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    // 调用策略的方法
    public void contextInterface() {
        System.out.print("Context is using strategy: ");
        strategy.algorithmInterface();
    }
}

// 客户端代码
public class StrategyPatternDemo {
    public static void main(String[] args) {
        // 使用策略A
        Context context = new Context(new ConcreteStrategyA());
        context.contextInterface();

        // 切换到策略B
        context.setStrategy(new ConcreteStrategyB());
        context.contextInterface();

        // 切换到策略C
        context.setStrategy(new ConcreteStrategyC());
        context.contextInterface();
    }
}

八.代码解析

  1. 抽象策略类 (Strategy)
    • 提供了一个算法接口,所有具体策略类必须实现这个接口。
  2. 具体策略类 (ConcreteStrategyA/B/C)
    • 每个具体类实现了不同的算法逻辑,满足抽象策略类的接口要求。
  3. 上下文类 (Context)
    • 持有一个策略对象的引用,调用策略的方法来实现算法的动态切换。
  4. 客户端代码
    • 创建具体策略类的实例,通过上下文调用算法。
    • 使用 SetStrategy 方法切换策略实现,体现了策略模式的灵活性。

九.总结

 策略模式通过将算法封装到独立的类中,实现了算法的互换性和扩展性。在需求经常变化的场景中,策略模式能够有效地减少代码的耦合度,提高系统的灵活性,是一种非常重要的设计模式。
实际应用案例

  1. 支付系统:支持多种支付方式(如微信支付、支付宝、银行卡),每种支付方式可以作为一个策略类。
  2. 日志记录:不同的日志记录方式(如文件、数据库、云存储)可以封装为策略。
  3. 排序算法:针对不同数据结构选择不同的排序算法(如快速排序、归并排序、冒泡排序)。
;