类图: 策略设计模式类图
一.什么是策略设计模式?
策略设计模式(Strategy Pattern)是一种行为型设计模式,定义了一系列算法,并将每种算法封装起来,使得它们可以互换使用。通过这种模式,算法的变化不会影响使用算法的上下文代码。
二.策略模式的特点
- 封装算法:将每种算法封装为独立的类,使得算法可以独立于使用它的客户端变化。
- 开放/关闭原则:通过新增策略类扩展新算法,而无需修改已有代码。
- 互换性:不同的策略实现可以互相替代,而不影响上下文。
三.策略模式的结构
- Context(上下文类):
- 持有一个 Strategy 对象的引用。
- 定义了操作接口,客户端通过上下文调用具体策略的方法。
- Strategy(抽象策略类):
- 定义所有具体策略的公共接口。
- 每个策略类都实现这个接口,提供不同的算法实现。
- ConcreteStrategy(具体策略类):
- 实现了抽象策略接口中的方法。
- 封装具体的算法逻辑。
四.策略模式的应用场景
- 需要动态选择算法或行为的场景。
- 算法具有多种实现方式,需要灵活切换。
- 避免大量条件语句,使代码更加清晰。
五.策略模式的优缺点
- 优点:
- 算法的独立性:每个策略类实现了独立的算法,便于维护和扩展。
- 代码清晰:避免了条件分支语句,提高了代码的可读性。
- 灵活性:通过上下文动态选择不同的策略实现。
- 缺点:
- 类数量增加:每种算法需要对应一个策略类,可能导致类数量较多。
- 上下文与策略耦合:上下文需要了解所有策略类的定义,增加了代码的复杂性。
六.策略模式的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();
}
}
八.代码解析
- 抽象策略类 (Strategy):
- 提供了一个算法接口,所有具体策略类必须实现这个接口。
- 具体策略类 (ConcreteStrategyA/B/C):
- 每个具体类实现了不同的算法逻辑,满足抽象策略类的接口要求。
- 上下文类 (Context):
- 持有一个策略对象的引用,调用策略的方法来实现算法的动态切换。
- 客户端代码:
- 创建具体策略类的实例,通过上下文调用算法。
- 使用 SetStrategy 方法切换策略实现,体现了策略模式的灵活性。
九.总结
策略模式通过将算法封装到独立的类中,实现了算法的互换性和扩展性。在需求经常变化的场景中,策略模式能够有效地减少代码的耦合度,提高系统的灵活性,是一种非常重要的设计模式。
实际应用案例:
- 支付系统:支持多种支付方式(如微信支付、支付宝、银行卡),每种支付方式可以作为一个策略类。
- 日志记录:不同的日志记录方式(如文件、数据库、云存储)可以封装为策略。
- 排序算法:针对不同数据结构选择不同的排序算法(如快速排序、归并排序、冒泡排序)。