介绍
策略模式(Strategy Pattern):封装了不同的算法,根据需求选择其一
简称:多选一
核心是上下文
使用场景
多选一适合策略模式,比如计算(加减乘除)、支付(微信、支付宝、数字人民币等)
案例
接口
public interface Calculator {
double cal(double numA,double numB);
}
实现类
@Bean("add")
public class AddCalculator implements Calculator{
public double cal(double numA, double numB) {
BigDecimal a = new BigDecimal(String.valueOf(numA));
BigDecimal b = new BigDecimal(String.valueOf(numB));
return a.add(b).doubleValue();
}
}
@Bean("div")
public class DivCalculator implements Calculator{
public double cal(double numA, double numB) {
BigDecimal a = new BigDecimal(String.valueOf(numA));
BigDecimal b = new BigDecimal(String.valueOf(numB));
return a.divide(b).doubleValue();
}
}
@Bean("mul")
public class MulCalculator implements Calculator{
public double cal(double numA, double numB) {
BigDecimal a = new BigDecimal(String.valueOf(numA));
BigDecimal b = new BigDecimal(String.valueOf(numB));
return a.multiply(b).doubleValue();
}
}
@Bean("sub")
public class SubCalculator implements Calculator{
public double cal(double numA, double numB) {
BigDecimal a = new BigDecimal(String.valueOf(numA));
BigDecimal b = new BigDecimal(String.valueOf(numB));
return a.subtract(b).doubleValue();
}
}
上下文类
- 找到算法(调用容器工厂)
- 调用算法返回结果
public class Context {
private static String PKG_NAME = "top.lldwb.StrategyPattern";
private static ContainerFactory containerFactory;
static {
containerFactory = new ContainerFactory(PKG_NAME);
}
public double executeCalculator(String type, double numA, double numB) {
Calculator calculator = containerFactory.getBean(type);
if (calculator == null) {
throw new RuntimeException("并没有找到计算方法");
}
return calculator.cal(numA, numB);
}
}
上下文类(使用Spring的依赖注入)
注入 map 集合中,spring 会将 所有实现类 注入集合中
集合中 key(Bean的id) value(实现类的对象)
根据集合中的 value 类型去进行查找并注入依赖
为什么不使用 List 而是使用 Map,因为 List 不能存储 Bean 的 ID
public class Context {
private final Map<String,Calculator> map;
public double executeCalculator(String type, double numA, double numB) {
Calculator calculator = map.get(type);
if (calculator == null) {
throw new RuntimeException("并没有找到计算方法");
}
return calculator.cal(numA, numB);
}
}
测试
public class Test {
@org.junit.jupiter.api.Test
public void test(){
Context context = new Context();
double num = context.executeCalculator("add",1,1);
System.out.println(num);
System.out.println(context.executeCalculator("add",1,1));
System.out.println(context.executeCalculator("div",1,1));
System.out.println(context.executeCalculator("mul",1,1));
System.out.println(context.executeCalculator("sub",1,1));
}
}
输出
2.0
2.0
1.0
1.0
0.0
优缺点
优点
- 算法可以自由切换
- 扩展性高
缺点
- 默认的简单工厂会有开闭原则的问题,但是使用容器工厂就不会有开闭原则的问题
- 如果算法多