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:使用策略时 不管是 策略对象是有状态还是无状态 都可以使用枚举获取传入的Type
2:在创建策略时
策略对象是无状态:可以把对象新建到 Map集合中 根据传入的Tpye 获取对象
策略对象是有状态:
1:可以把对象新建到 Map集合中,根据传入的Tpye 获取对象
然后使用JsonObject复制策略对象返回
2:使用枚举 根据传入的Type获取对象
策略模式与工厂模式对比
策略模式 注重 策略的选择
工厂模式 注重 对象的创建
策略模式 :策略的创建由工厂类(非真正意义的工厂)来完成,封装策略创建的细节。
工厂模式 :工厂创建对象时,由于内部工厂都是重新创建对象,而外部工厂是无状态的。
理解为两个工厂:外部工厂 创建 创建对象的内部工厂
因此可以使用策略思维,使用Map存放无状态的外部工厂。
项目连接
请配合项目代码食用效果更佳:
项目地址:
https://github.com/hesuijin/hesujin-design-pattern
Git下载地址:
https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.git
demo-study模块 下 behavior_design_pattern strategy包
网友评论