策略模式
1/22/24About 4 min
策略模式定义了一组能够用来表示可能行为集合的类。这些行为可以在应用程序中使用,来修改应用程序功能。

策略模式(Strategy pattern)包含以下三个主要角色:
抽象策略角色(Strategy):定义所有支持的算法的公共接口。在面向对象设计中,通常是一个接口或抽象类,它声明了具体策略角色需要实现的方法。
具体策略角色(ConcreteStrategy):实现了抽象策略角色所定义的接口,提供了具体的算法实现。根据情况的不同,可以有多个具体策略角色,每个都提供不同的行为实现。
环境角色(StrategyContext):持有一个策略类的引用,并且使用该策略来执行相关的操作。环境角色可以根据运行时条件改变其使用的具体策略。通过与抽象策略角色交互,环境角色独立于具体的策略实现细节。
代码实现
抽象策略
抽象策略定义了一个抽象的行为。
public abstract class Strategy {
public abstract void algorithmInterface();
}具体策略
具体角色用于实现这个抽象行为,且支持多种实现方式。
public class ConcreteStrategyA extends Strategy{
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyA.algorithmInterface()");
}
}你可以继续创建ConcreteStrategyB、 ConcreteStrategyC。
环境角色
环境角色使用具体的策略角色来执行操作。它包含了一个策略对象的引用。
public class StrategyContext {
private Strategy strategy;
public StrategyContext(Strategy strategy) {
this.strategy = strategy;
}
public void contextInterface() {
strategy.algorithmInterface();
}
}具体策略B和C
public class ConcreteStrategyB extends Strategy{
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyB.algorithmInterface()");
}
}
public class ConcreteStrategyC extends Strategy{
@Override
public void algorithmInterface() {
System.out.println("ConcreteStrategyC.algorithmInterface()");
}
}使用
在Client类中我们指定不同的策略进行调用。
public class Client {
public static void main(String[] args) {
StrategyContext contextA = new StrategyContext(new ConcreteStrategyA());
contextA.contextInterface();
StrategyContext contextB = new StrategyContext(new ConcreteStrategyB());
contextB.contextInterface();
StrategyContext contextC = new StrategyContext(new ConcreteStrategyC());
contextC.contextInterface();
}
}运行结果:
ConcreteStrategyA.algorithmInterface()
ConcreteStrategyB.algorithmInterface()
ConcreteStrategyC.algorithmInterface()与其他设计模式的对比
| 设计模式 | 主要功能 | 实现方式 | 适用场景 |
|---|---|---|---|
| 策略模式 | 算法替换 | 组合 | 算法需要频繁切换时 |
| 状态模式 | 状态转换与行为切换 | 组合 + 状态管理 | 对象行为随状态变化时 |
| 模板方法模式 | 算法骨架固定 | 继承 | 算法骨架不变,步骤可变时 |
| 装饰器模式 | 动态扩展功能 | 组合 + 继承 | 需要动态添加功能时 |
总结
核心思想
策略模式通过组合的方式,定义一系列算法,并将每一个算法封装起来,使它们可以相互替换,让算法的变化独立于使用该算法的客户。
主要角色
- 抽象策略(Strategy):定义所有支持的算法的公共接口
- 具体策略(ConcreteStrategy):实现抽象策略接口,提供具体的算法实现
- 环境角色(StrategyContext):持有一个策略类的引用,使用该策略执行相关操作
实现方式
- 使用组合而非继承来实现算法的动态切换
- 策略类之间相互独立,便于扩展和维护
- 环境类与策略类解耦,符合开闭原则
优点
- 灵活性:可以在运行时动态切换算法
- 可扩展性:新增算法只需添加新的策略类,无需修改现有代码
- 可读性:将不同算法封装在独立的策略类中,提高代码可读性
- 避免条件判断:消除了大量的条件判断语句
缺点
- 客户端必须知道所有策略:客户端需要了解所有可用的策略才能选择合适的策略
- 策略类数量可能增多:每个算法都需要一个对应的策略类
- 策略类可能需要共享状态:如果策略类需要共享状态,可能需要额外的设计
适用场景
- 当一个系统需要动态地在几种算法中选择一种时
- 当一个对象有很多行为,而且这些行为如果使用条件语句实现会导致代码混乱时
- 当需要避免使用难以维护的多重条件判断语句时
- 当需要隐藏算法的具体实现细节时
实际应用
- Java中的Comparator接口
- Spring中的Resource接口实现
- 排序算法的动态选择
- 支付方式的动态切换
- 日志级别和格式的动态配置