设计模式之策略模式(Strategy Design Pattern)

策略模式,是11种行为型模式之一。在 GoF 的《设计模式》一书中,它是这样定义的:Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.翻译成中文就是:定义一系列算法(策略),封装每一个算法(策略),并使它们可以互换。使算法(策略)可以独立于使用它的客户端(调用者)而变化。

策略模式分为简单策略模式和复合策略模式。简单策略模式跟桥接模式一样,但应用场景不同。复合策略模式是为了让策略可以运行时动态调用而混合工厂模式。不多说看先看代码。

未使用策略模式:

class Client {

   String type;
   Client(String type) {
     this.type = type;
   }

   public String operate() {
     String result = null;
     if("A".equals(type)) {
        //省略代码 策略A
     } else if("B".equals(type)) {
        //省略代码 策略B
     } else {
        //省略代码 策略B
     }
     return result;
   }
}

简单策略模式:

interface Strategy {
  public String operate(省略参数);
}

//A策略
class AStrategy {
   public String operate(省略参数){
      //省略代码
   }
}

//省略BStrategy  CStrategy 

class Client {
   Strategy strategy;
   Client(Strategy strategy){
     this.strategy = strategy;
   }
   public String operate() {
     return strategy.operate(省略参数)
   }
}

class Demo {
  public static void main(String[] args) {
      Client client = new Client(new AStrategy());    
      System.out.println("a = " + client.operate());
 
      client = new Client(new BStrategy());      
      System.out.println("b = " + client.operate());
   }

}

简单策略模式需要调用者事先选择策略,如果要换策略,需要修改代码。不能根据代码的情况动态选择策略。

所谓动态选择策略就是可以在程序运行期间,根据配置、用户输入、计算结果等这些不确定因素,动态决定使用哪种策略。既然是动态的使用策略,就需要动态的创建策略。动态的创建对象使用工厂模式最合适不过了。

//省略策略定义


//如果策略类是无状态的,使用下面缓存方式共享策略
public class StrategyFactory {
  private static final Map<String, Strategy> strategies = new HashMap<>();

  static {
    strategies.put("A", new AStrategy());
    strategies.put("B", new BStrategy());
  }

  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }
    return strategies.get(type);
  }
}

或者

//如果策略类是有状态的,使用每次创建新策略的方式
public class StrategyFactory {
  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }

    if (type.equals("A")) {
      return new AStrategy();
    } else if (type.equals("B")) {
      return new BStrategy();
    }

    return null;
  }
}

// 非运行时动态确定,在代码中指定使用哪种策略
public class Demo{
  public static void main(String[] args) {

    Strategy strategy = new BStrategy();
    Client client = new Client(strategy);    
    System.out.println(client.operate());

  }
}


// 运行时动态确定,根据配置文件的配置决定使用哪种策略
public class Demo{
  public static void main(String[] args) throws Exception {
    Properties props = new Properties();
    props.load(new FileInputStream("./config.properties"));
    String type = props.getProperty("strategy_type");
    Strategy strategy = StrategyFactory.getStrategy(type);
 
    Client client = new Client(strategy);    
    System.out.println(client.operate());
  }
}

策略模式遵循的设计原则和思想:

  • 面向接口编程的思想:把策略抽象成接口;
  • 多用组合少用继承的思想:调用者以聚合方式的使用策略;
  • 单一职责原则:把策略代码提取到单独的策略类,策略类和调用者的职责更加单一;
  • DRY原则:把策略代码提取到单独的策略类,可以重复使用;
  • 开闭原则:把策略与调用者解耦,使用策略可以单独扩展,而不影响调用者;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值