目录与学习目标
1:策略模式的问题2:如何避免 if -else(策略创建)3:如何避免 if -else(策略使用)4:策略模式 总结
1:策略模式的问题
假如策略是无状态的 1:策略创建的时候可以使用Map来缓存无状态的对象(已解决)2:但是在进入策略前 假如入参type还没有确定 还是需要使用if-else 来获取type(未解决)假如策略是有状态的 1:策略创建的时候就需要大量的if-else 来判断创建哪个策略对象(未解决)2:同时在进入策略前 假如入参type还没有确定 还是需要使用if-else 来获取type(未解决)那么实际上还有一个很严重的问题 如何避免 if-else来获取type呢
2:如何避免 if -else(策略创建)
一个很好的选择方法就是通过枚举 假如 现在策略创建的对象是有状态 如何避免大量的if-else来创建对象
public class StrategyFactoryStateEnum { public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } //使用枚举获取对象 return StrategyEnum.getStrategyeByName(type); }}
public enum StrategyEnum { ConcreteStrategyA("ConcreteStrategyA",new ConcreteStrategyA()), ConcreteStrategyB("ConcreteStrategyB",new ConcreteStrategyB()); private String name; private Strategy strategy; StrategyEnum(String name , Strategy strategy){ this.name = name; this.strategy = strategy; } public String getName() { return name; } public Strategy getStrategy() { return strategy; } //根据名称遍历 获取对应的对象 public static Strategy getStrategyeByName(String name){ if (StringUtils.isEmpty(name)){ return null; } for (StrategyEnum strategyEnum : StrategyEnum.values()) { if (name.equals(strategyEnum.getName())){ return strategyEnum.getStrategy(); } } return null; }}
突然发现使用枚举的方式 和 在无状态策略 中Map根据key值获取value的方式非常像那么能否使用无状态策略中的Map来获取对应的对象呢稍微做修改即可 使用深拷贝的方法获取复制出一个该type对应的对象
public class StrategyFactoryStatelessEnum { private static final Map<String, Strategy> strategies = new HashMap<>(); static { strategies.put("ConcreteStrategyA", new ConcreteStrategyA()); strategies.put("ConcreteStrategyB", new ConcreteStrategyB()); } public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } //使用JSONObject进行深拷贝 Strategy strategy = JSONObject.parseObject(JSONObject.toJSONString(strategies.get(type)), Strategy.class); return strategy; }}
3:如何避免 if -else(策略使用)
现在策略的创建 不管是无状态 还是有状态 都可以通过 Map或者枚举的方式来获取 type对应的对象那么在使用策略 如何避免if-else 来获取对应的type呢实际上也是同样的可以用枚举的方式获取Tpye在上述的StrategyFactoryStateEnum中我们既然可以根据相应的Type获取相应的对象那么实际上我们也可以同样 使用相同的逻辑获取相应的Type最终在代码主逻辑可能会传入 Int Long String 等类型的值 使用枚举获取对应的Type即可
public enum StrategyTypeEnum { ConcreteStrategyTypeA("ConcreteStrategyNameA","ConcreteStrategyA"), ConcreteStrategyTypeB("ConcreteStrategyNameB","ConcreteStrategyB"); private String name; private String strategyType; StrategyTypeEnum(String name , String strategyType){ this.name = name; this.strategyType = strategyType; } public String getName() { return name; } public String getStrategyType() { return strategyType; } //根据名称遍历 获取对应的对象 public static String getStrategyeByName(String name){ if (StringUtils.isEmpty(name)){ return null; } for (StrategyTypeEnum strategyTypeEnum : StrategyTypeEnum.values()) { if (name.equals(strategyTypeEnum.getName())){ return strategyTypeEnum.getStrategyType(); } } return null; }}
4:策略模式 总结
1:使用策略时 不管是 策略对象是有状态还是无状态 都可以使用枚举获取传入的Type2:在创建策略时 策略对象是无状态:可以把对象新建到 Map集合中 根据传入的Tpye 获取对象 策略对象是有状态: 1:可以把对象新建到 Map集合中,根据传入的Tpye 获取对象 然后使用JsonObject复制策略对象返回 2:使用枚举 根据传入的Type获取对象
策略模式与工厂模式对比策略模式 注重 策略的选择工厂模式 注重 对象的创建策略模式 :策略的创建由工厂类(非真正意义的工厂)来完成,封装策略创建的细节。工厂模式 :工厂创建对象时,由于内部工厂都是重新创建对象,而外部工厂是无状态的。 理解为两个工厂:外部工厂 创建 创建对象的内部工厂 因此可以使用策略思维,使用Map存放无状态的外部工厂。
项目连接
请配合项目代码食用效果更佳:项目地址:https://github.com/hesuijin/hesujin-design-patternGit下载地址:https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.gitdemo-study模块 下 behavior_design_pattern strategy包