目录与学习目标

  1. 1:策略模式的问题
  2. 2:如何避免 if -else(策略创建)
  3. 3:如何避免 if -else(策略使用)
  4. 4:策略模式 总结

1:策略模式的问题

  1. 假如策略是无状态的
  2. 1:策略创建的时候可以使用Map来缓存无状态的对象(已解决)
  3. 2:但是在进入策略前 假如入参type还没有确定 还是需要使用if-else 来获取type(未解决)
  4. 假如策略是有状态的
  5. 1:策略创建的时候就需要大量的if-else 来判断创建哪个策略对象(未解决)
  6. 2:同时在进入策略前 假如入参type还没有确定 还是需要使用if-else 来获取type(未解决)
  7. 那么实际上还有一个很严重的问题 如何避免 if-else来获取type

2:如何避免 if -else(策略创建)

  1. 一个很好的选择方法就是通过枚举
  2. 假如 现在策略创建的对象是有状态 如何避免大量的if-else来创建对象
  1. public class StrategyFactoryStateEnum {
  2. public static Strategy getStrategy(String type) {
  3. if (type == null || type.isEmpty()) {
  4. throw new IllegalArgumentException("type should not be empty.");
  5. }
  6. //使用枚举获取对象
  7. return StrategyEnum.getStrategyeByName(type);
  8. }
  9. }
  1. public enum StrategyEnum {
  2. ConcreteStrategyA("ConcreteStrategyA",new ConcreteStrategyA()),
  3. ConcreteStrategyB("ConcreteStrategyB",new ConcreteStrategyB());
  4. private String name;
  5. private Strategy strategy;
  6. StrategyEnum(String name , Strategy strategy){
  7. this.name = name;
  8. this.strategy = strategy;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public Strategy getStrategy() {
  14. return strategy;
  15. }
  16. //根据名称遍历 获取对应的对象
  17. public static Strategy getStrategyeByName(String name){
  18. if (StringUtils.isEmpty(name)){
  19. return null;
  20. }
  21. for (StrategyEnum strategyEnum : StrategyEnum.values()) {
  22. if (name.equals(strategyEnum.getName())){
  23. return strategyEnum.getStrategy();
  24. }
  25. }
  26. return null;
  27. }
  28. }
  1. 突然发现使用枚举的方式 在无状态策略 Map根据key值获取value的方式非常像
  2. 那么能否使用无状态策略中的Map来获取对应的对象呢
  3. 稍微做修改即可 使用深拷贝的方法获取复制出一个该type对应的对象
  1. public class StrategyFactoryStatelessEnum {
  2. private static final Map<String, Strategy> strategies = new HashMap<>();
  3. static {
  4. strategies.put("ConcreteStrategyA", new ConcreteStrategyA());
  5. strategies.put("ConcreteStrategyB", new ConcreteStrategyB());
  6. }
  7. public static Strategy getStrategy(String type) {
  8. if (type == null || type.isEmpty()) {
  9. throw new IllegalArgumentException("type should not be empty.");
  10. }
  11. //使用JSONObject进行深拷贝
  12. Strategy strategy = JSONObject.parseObject(JSONObject.toJSONString(strategies.get(type)), Strategy.class);
  13. return strategy;
  14. }
  15. }

3:如何避免 if -else(策略使用)

  1. 现在策略的创建 不管是无状态 还是有状态 都可以通过 Map或者枚举的方式来获取 type对应的对象
  2. 那么在使用策略 如何避免if-else 来获取对应的type
  3. 实际上也是同样的可以用枚举的方式获取Tpye
  4. 在上述的StrategyFactoryStateEnum
  5. 我们既然可以根据相应的Type获取相应的对象
  6. 那么实际上我们也可以同样 使用相同的逻辑获取相应的Type
  7. 最终在代码主逻辑可能会传入 Int Long String 等类型的值 使用枚举获取对应的Type即可
  1. public enum StrategyTypeEnum {
  2. ConcreteStrategyTypeA("ConcreteStrategyNameA","ConcreteStrategyA"),
  3. ConcreteStrategyTypeB("ConcreteStrategyNameB","ConcreteStrategyB");
  4. private String name;
  5. private String strategyType;
  6. StrategyTypeEnum(String name , String strategyType){
  7. this.name = name;
  8. this.strategyType = strategyType;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public String getStrategyType() {
  14. return strategyType;
  15. }
  16. //根据名称遍历 获取对应的对象
  17. public static String getStrategyeByName(String name){
  18. if (StringUtils.isEmpty(name)){
  19. return null;
  20. }
  21. for (StrategyTypeEnum strategyTypeEnum : StrategyTypeEnum.values()) {
  22. if (name.equals(strategyTypeEnum.getName())){
  23. return strategyTypeEnum.getStrategyType();
  24. }
  25. }
  26. return null;
  27. }
  28. }

4:策略模式 总结

  1. 1:使用策略时 不管是 策略对象是有状态还是无状态 都可以使用枚举获取传入的Type
  2. 2:在创建策略时
  3. 策略对象是无状态:可以把对象新建到 Map集合中 根据传入的Tpye 获取对象
  4. 策略对象是有状态:
  5. 1:可以把对象新建到 Map集合中,根据传入的Tpye 获取对象
  6. 然后使用JsonObject复制策略对象返回
  7. 2:使用枚举 根据传入的Type获取对象

  1. 策略模式与工厂模式对比
  2. 策略模式 注重 策略的选择
  3. 工厂模式 注重 对象的创建
  4. 策略模式 :策略的创建由工厂类(非真正意义的工厂)来完成,封装策略创建的细节。
  5. 工厂模式 :工厂创建对象时,由于内部工厂都是重新创建对象,而外部工厂是无状态的。
  6. 理解为两个工厂:外部工厂 创建 创建对象的内部工厂
  7. 因此可以使用策略思维,使用Map存放无状态的外部工厂。

项目连接

  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