CodeArena

借助Spring实现策略模式

2023-04-13
Spring
最后更新:2024-05-23
4分钟
768字

借助 Spring 实现策略模式


策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。

应用场景:

  • 计算商品优惠的时候会有各种优惠券,满减券、奖金券、折扣券等
  • 抽奖过程中会使用到多种不同的抽奖算法

合理地使用策略模式可以让代码更具有可维护性,替代了大量的 if-else 语句。

策略模式通常和模板模式结合在一起使用,模板模式用于定义算法骨架,而策略模式则用于定义算法中的可变部分。

策略模式总结起来有以下几个部分:

  1. 抽象策略类(Strategy):策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。
  2. 具体策略类(ConcreteStrategy):实现抽象策略中的操作,含有具体的算法。
  3. 环境类(Context):持有一个策略类的引用,最终给客户端调用。

如何借助 Spring 实现策略模式?

  1. 定义抽象策略类(Strategy):
1
public interface Strategy implements InitializingBean{
2
/**
3
* 策略方法
4
*/
5
void doSomething();
6
7
8
/**
9
* 设置策略key
10
*/
11
int getStrategyKey();
12
13
@Override
14
default void afterPropertiesSet() throws Exception {
15
int key = getStrategyKey();
3 collapsed lines
16
Context.registerStrategy(key, this);
17
}
18
}
  1. 定义具体策略类(ConcreteStrategy):
1
public class ConcreteStrategyA implements Strategy {
2
@Override
3
public void doSomething() {
4
System.out.println("具体策略A的实现");
5
}
6
7
@Override
8
public int getStrategyKey() {
9
return 1;
10
}
11
}
1
public class ConcreteStrategyB implements Strategy {
2
@Override
3
public void doSomething() {
4
System.out.println("具体策略B的实现");
5
}
6
7
@Override
8
public int getStrategyKey() {
9
return 2;
10
}
11
}
  1. 定义环境类(Context):
1
public class Context {
2
private Map<Integer, Strategy> strategyMap = new HashMap<>();
3
4
public static registerStrategy(int key, Strategy strategy) {
5
strategyMap.put(key, strategy);
6
}
7
8
public void doAnything(int key) {
9
Strategy strategy = strategyMap.get(key);
10
strategy.doSomething();
11
}
12
}
  1. 测试
1
public class Test {
2
public static void main(String[] args) {
3
Context context = new Context();
4
context.doAnything(1);
5
6
context = new Context(new ConcreteStrategyB());
7
context.doAnything(2);
8
}
9
}

InitializingBean

InitializingBean的作用是Bean注入到Spring容器且初始化后,执行特定业务化的操作。

Spring允许容器中的Bean,在Bean初始化完成后或者Bean销毁前,执行特定业务化的操作,常用的实现方式有以下三种:

  • 通过实现InitializingBean/DisposableBean接口来处理初始化后/销毁前的操作;
  • 通过标签的init-method/destroy-method属性处理初始化后/销毁前的操作;
  • 在指定方法上加上@PostConstruct或@PreDestroy注解来处理初始化后/销毁前的操作

如果采用实现InitializingBean接口的方式去执行特定业务化的操作,则需要重写afterPropertiesSet这个方法

优化

我们还可以基于注解的方式来标注具体的策略类,结合PostConstruct注解,我们可以将注解标注在具体的策略类上,这样我们就可以在初始化后执行特定业务化的操作。

1
@Target({ElementType.TYPE})
2
@Retention(RetentionPolicy.RUNTIME)
3
public @interface StrategyAnnoation {
4
Constants.StrategyMode strategyMode();
5
}
1
public enum StrategyMode {
2
3
SINGLE(1, "策略A"),
4
5
ENTIRETY(2, "策略B");
6
7
private Integer code;
8
private String info;
9
10
StrategyMode(Integer code, String info) {
11
this.code = code;
12
this.info = info;
13
}
14
15
...getter/setter
1 collapsed line
16
}
1
public class Context {
2
3
@Resource
4
private List<Strategy> strategyList;
5
6
protected static Map<Integer, Strategy> strategyGroup = new ConcurrentHashMap<>();
7
8
@PostConstruct
9
public void init() {
10
strategyList.forEach(strategy -> {
11
Strategy strategy = AnnotationUtils.findAnnotation(strategy.getClass(), StrategyAnnoation.class);
12
if (null != strategy) {
13
strategyGroup.put(strategy.strategyMode().getCode(), strategy);
14
}
15
});
3 collapsed lines
16
}
17
18
}
本文标题:借助Spring实现策略模式
文章作者:Echoidf
发布时间:2023-04-13
感谢大佬送来的咖啡☕
alipayQRCode
wechatQRCode