策略模式及使用Spring实现策略模式+工厂模式

一、策略模式

策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换

1、策略模式主要角色

《策略模式及使用Spring实现策略模式+工厂模式》

主要角色如下

  • 封装角色(Context):也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化
  • 抽象策略角色(Strategy):策略家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
  • 具体策略角色(ConcreteStrategy):实现抽象策略中的操作,该类含有具体的算法

2、实现策略模式

//抽象策略角色
public interface Strategy { 
    //策略模式的运算法则
    void doSomething();
}
//具体策略角色
public class ConcreteStrategy1 implements Strategy { 
    @Override
    public void doSomething() { 
        System.out.println("具体策略1的运算法则...");
    }
}
//具体策略角色
public class ConcreteStrategy2 implements Strategy { 
    @Override
    public void doSomething() { 
        System.out.println("具体策略2的运算法则...");
    }
}
//封装角色
public class Context { 
    //抽象策略
    private Strategy strategy;

    //构造函数设置具体策略
    public Context(Strategy strategy) { 
        this.strategy = strategy;
    }

    //封装后的策略方法
    public void doAnything() { 
        this.strategy.doSomething();
    }
}
public class Client { 
    public static void main(String[] args) { 
        //声明一个具体的策略
        Strategy strategy = new ConcreteStrategy1();
        //声明上下文对象
        Context context = new Context(strategy);
        //执行封装后的方法
        context.doAnything();
    }
}

执行结果如下:

具体策略1的运算法则...

二、使用Spring实现策略模式+工厂模式

1、实现策略类

public interface Strategy { 
    //策略模式的运算法则
    void doSomething();
}
@Component
public class ConcreteStrategy1 implements Strategy { 
    @Override
    public void doSomething() { 
        System.out.println("具体策略1的运算法则...");
    }

    @Override
    public String toString() { 
        return "具体策略1";
    }
}
@Component
public class ConcreteStrategy2 implements Strategy { 
    @Override
    public void doSomething() { 
        System.out.println("具体策略2的运算法则...");
    }

    @Override
    public String toString() { 
        return "具体策略2";
    }
}
@Component
public class DefaultStrategy implements Strategy { 
    @Override
    public void doSomething() { 
        System.out.println("默认策略的运算法则...");
    }

    @Override
    public String toString() { 
        return "默认策略";
    }
}

2、实现工厂类

@Component
public class StrategyFactory { 
    //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
    @Autowired
    private Map<String, Strategy> strategyMap;

    public Strategy getBy(String strategyName) { 
        return strategyMap.get(strategyName);
    }
}

Spring会自动将Strategy接口的实现类注入到这个Map中(前提是实现类得是交给Spring 容器管理的),这个Map的key为bean id,可以用@Component(value = "xxx")的方式设置,如果直接用默认的方式的话,就是首字母小写。value值则为对应的策略实现类

《策略模式及使用Spring实现策略模式+工厂模式》

测试类:

@SpringBootTest
class SpringbootDemoApplicationTests { 

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() { 
        context.getBean(StrategyFactory.class).getBy("concreteStrategy1").doSomething();
        context.getBean(StrategyFactory.class).getBy("concreteStrategy2").doSomething();
    }

}

执行结果如下:

具体策略1的运算法则...
具体策略2的运算法则...

3、别名转换

上面测试类调用的使用使用的bean id,实际业务中应该是将传入的code转义成对应的策略类的bean id

@Component
@PropertySource("classpath:application.properties")
@ConfigurationProperties(prefix = "strategy")
public class StrategyAliasConfig { 
    private HashMap<String, String> aliasMap;

    public static final String DEFAULT_STATEGY_NAME = "defaultStrategy";

    public HashMap<String, String> getAliasMap() { 
        return aliasMap;
    }

    public void setAliasMap(HashMap<String, String> aliasMap) { 
        this.aliasMap = aliasMap;
    }

    public String of(String entNum) { 
        return aliasMap.get(entNum);
    }
}

配置文件application.properties

strategy.aliasMap.strategy1=concreteStrategy1
strategy.aliasMap.strategy2=concreteStrategy2
@Component
public class StrategyFactory { 
    @Autowired
    private StrategyAliasConfig strategyAliasConfig;

    //Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
    @Autowired
    private Map<String, Strategy> strategyMap;

    //找不到对应的策略类,使用默认的
    public Strategy getBy(String strategyName) { 
        String name = strategyAliasConfig.of(strategyName);
        if (name == null) { 
            return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
        }
        Strategy strategy = strategyMap.get(name);
        if (strategy == null) { 
            return strategyMap.get(StrategyAliasConfig.DEFAULT_STATEGY_NAME);
        }
        return strategy;

    }
}

测试类:

@SpringBootTest
class SpringbootDemoApplicationTests { 

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() { 
        context.getBean(StrategyFactory.class).getBy("strategy1").doSomething();
        context.getBean(StrategyFactory.class).getBy("strategy2").doSomething();
    }

}

执行结果如下:

具体策略1的运算法则...
具体策略2的运算法则...

参考:

《设计模式之禅》

https://mp.weixin.qq.com/s/cc4Slm0Ta22PShYuKpO2mQ

    原文作者:邋遢的流浪剑客
    原文地址: https://blog.csdn.net/qq_40378034/article/details/104121363
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞