一、策略模式
策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换
1、策略模式主要角色
image.png
主要角色如下:
- 封装角色(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 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值则为对应的策略实现类
image.png
测试类:
@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的运算法则...