目录与学习目标

  1. 1:什么是策略模式?
  2. 2:策略的定义
  3. 3:策略的创建
  4. 4:策略的使用

1:什么是策略模式?

  1. 策略模式解耦的是:定义 创建 使用 这三部分
  2. 定义一族算法(逻辑)类,将每个算法分别封装起来,让它们可以互相替换。
  3. 策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。
  4. 注意:
  5. 策略是分有状态和无状态的(后面会提及)
  6. 注意:
  7. 工厂模式主要逻辑在于 创建
  8. 策略模式主要逻辑在于 使用

2:策略的定义

  1. 策略类的定义比较简单,包含一个策略接口和一组实现这个接口的策略类。
  2. 因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略。
  1. public interface Strategy {
  2. void algorithmInterface();
  3. }
  4. public class ConcreteStrategyA implements Strategy {
  5. @Override
  6. public void algorithmInterface() {
  7. //具体逻辑
  8. System.out.println("我是ConcreteStrategyA 的算法逻辑");
  9. }
  10. }
  11. public class ConcreteStrategyB implements Strategy {
  12. @Override
  13. public void algorithmInterface() {
  14. //具体逻辑
  15. System.out.println("我是ConcreteStrategyB 的算法逻辑");
  16. }
  17. }

3:策略的创建

  1. 因为策略模式会包含一组策略,在使用它们的时候,一般会通过类型(type)来判断创建哪个策略来使用。
  2. 为了封装创建逻辑,我们需要对客户端代码屏蔽创建细节。
  3. 我们可以把根据 type 创建策略的逻辑抽离出来,放到工厂类中。

  1. 如果策略类是无状态的,不包含成员变量,只是纯粹的算法实现,
  2. 这样的策略对象是可以被共享使用的,
  3. 不需要在每次调用 getStrategy() 的时候,都创建一个新的策略对象。
  4. 如果策略类是有状态的,根据业务场景的需要,
  5. 我们希望每次从工厂方法中,获得的都是新创建的策略对象,
  6. 而不是缓存好可共享的策略对象,那我们就需要每次都重新创建一个对象
  1. //无状态 可以缓存对象
  2. public class StrategyFactoryStateless {
  3. private static final Map <String,Strategy> strategies = new HashMap<>();
  4. static {
  5. strategies.put("ConcreteStrategyA", new ConcreteStrategyA());
  6. strategies.put("ConcreteStrategyB", new ConcreteStrategyB());
  7. }
  8. public static Strategy getStrategy(String type) {
  9. if (type == null || type.isEmpty()) {
  10. throw new IllegalArgumentException("type should not be empty.");
  11. }
  12. return strategies.get(type);
  13. }
  14. }
  1. //有状态 需要创建对象
  2. public class StrategyFactoryState {
  3. public static Strategy getStrategy(String type) {
  4. if (type == null || type.isEmpty()) {
  5. throw new IllegalArgumentException("type should not be empty.");
  6. }
  7. if("ConcreteStrategyA".equals(type)){
  8. return new ConcreteStrategyA();
  9. }else if ("ConcreteStrategyB".equals(type)){
  10. return new ConcreteStrategyB();
  11. }
  12. return null;
  13. }
  14. }

4:策略的使用

  1. 策略模式包含一组可选策略,客户端代码一般如何确定使用哪个策略呢?
  2. 运行时动态确定使用哪种策略: 在程序运行期间,根据配置、用户输入、计算结果等这些不确定因素,动态决定使用哪种策略策略模式;
  3. 非运行时动态指定使用哪种策略:并不能发挥策略模式的优势,退化成了“面向对象的多态特性”或“基于接口而非实现编程原则”
  1. private static void strategyOne() throws IOException {
  2. //运行时动态 根据配置文件的配置决定使用哪种策略
  3. Properties props = new Properties();
  4. props.load(new FileInputStream("./config.properties"));
  5. String strategyType = props.getProperty("eviction_type");
  6. StrategyFactoryStateless strategyFactoryStateless = new StrategyFactoryStateless();
  7. Strategy strategy = strategyFactoryStateless.getStrategy(strategyType);
  8. strategy.algorithmInterface();
  9. }
  1. private static void strategyTwo() {
  2. //非运行时动态 在代码中指定使用哪种策略
  3. StrategyFactoryStateless strategyFactoryStateless = new StrategyFactoryStateless();
  4. Strategy strategy = strategyFactoryStateless.getStrategy("ConcreteStrategyB");
  5. strategy.algorithmInterface();
  6. }

项目连接

  1. 请配合项目代码食用效果更佳:
  2. 项目地址:
  3. https://github.com/hesuijin/hesujin-design-pattern
  4. Git下载地址:
  5. https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.git
  6. demo-study模块 behavior_design_pattern strategy