Skip to content

策略模式

定义

Define a family of algorithm, encapsulate each one, and make them interchangeable.
定义一组算法,并将每个算法都封装起来,并且使它们之间可以互相替换。

常见结构

Strategy            // 抽象的策略角色
ConcreteStrategy    // 具体的策略类
Context             // 持有策略实例

策略模式的重点是封装角色,借用了代理模式的思路。

应用

优点

  • 算法可以自由切换
  • 避免使用多重条件判断
  • 扩展性良好

缺点

  • 策略类数量增多 每一个策略都是一个类,复用的可能性小,类数量很多
  • 所有的策略类都需要对外暴露

使用场景

  • 多个类只有在算法或者行为上稍有不同的场景
  • 算法需要自由切换的场景
  • 需要屏蔽算法规则的场景

注意事项,如果系统中的一个策略家族的具体策略数量超过4个,则需考虑使用混合模式,解决策略类 膨胀和对外暴露的问题。

代码示例

策略模式示例

文件目录

strategy/
|-- Add.java            // 具体的策略
|-- Division.java       // 具体的策略
|-- IStrategy.java      // 策略接口
|-- Minus.java          // 具体的策略
|-- Paper.java          // 测试代码
`-- StrategyContext.java// 上下文角色,承上启下

首先看策略接口类,定义了一个方法

public interface IStrategy {

    float compute(float a, float b);

}

上下文类,屏蔽了高层模块对策略、算法的直接访问

public class StrategyContext {
    private IStrategy strategy;

    public void setStrategy(IStrategy strategy) {
        this.strategy = strategy;
    }

    public StrategyContext(IStrategy strategy) {
        this.strategy = strategy;
    }

    public float calculate(float a, float b) {
       return this.strategy.compute(a, b);
    }

}

具体的策略类

public class Add implements IStrategy {
    @Override
    public float compute(float a, float b) {
        return a + b;
    }
}
public class Minus implements IStrategy {
    @Override
    public float compute(float a, float b) {
        return a - b;
    }
}
public class Division implements IStrategy {
    @Override
    public float compute(float a, float b) {
        return a / b;
    }
}

测试代码

    StrategyContext context = new StrategyContext(new Add());
    System.out.println("Add Res = " + context.calculate(1, 3));
    context.setStrategy(new Minus());
    System.out.println("Minus Res = " + context.calculate(14, 8));
    context.setStrategy(new Division());
    System.out.println("Division Res = " + context.calculate(12, 5));

output

Add Res = 4.0
Minus Res = 6.0
Division Res = 2.4

枚举策略示例

使用枚举类来封装策略。

public enum Calculator {
    ADD("+") {
        public float exec(float a, float b) {
            return a + b;
        }
    },
    SUB("-") {
        public float exec(float a, float b) {
            return a - b;
        }
    };
    String value;

    Calculator(String _value) {
        this.value = _value;
    }

    public String getValue() {
        return value;
    }

    public abstract float exec(float a, float b);
}

测试代码和输出

    System.out.println("ENUM ADD Res = " + Calculator.ADD.exec(12, 5));
    System.out.println("ENUM SUB Res = " + Calculator.SUB.exec(2, 5));

// output
ENUM ADD Res = 17.0
ENUM SUB Res = -3.0

参考:《设计模式之禅》 秦小波