策略模式
策略模式解决的痛点是多个if else 进行条件判断从而处理不同的逻辑,提高代码的可维护性、
可扩展性、可读性。
策略模式的逻辑
1、创建一个最上层的策略接口,定义策略的方法
//此接口定义策略类的公共方法
interface Categry(){
TypeEnum getType(); //获取策略的类型
Result doProcess(); //各策略类的实现的正式逻辑
}
2、创建各自的策略类,实现策略接口和对应的方法
策略类A
class CategryA implements(){
//获取策略的类型
TypeEnum getType(){
//TODO
}
//各策略类的实现的正式逻辑
Result doProcess();{
//TODO
}
}
//////////////////////////////////
策略类B
class CategryB implements(){
//获取策略的类型
TypeEnum getType(){
//TODO
}
//各策略类的实现的正式逻辑
Result doProcess();{
//TODO
}
}
3、将所有策略类注入到内存中(可以通过工厂模式 或者spring的方式去注入),并且实现根据类型获取策略类的方法
下面是使用spring的方式去注入保存各个策略类
class xxxxManager() implements InitializingBean,ApplicationContextAware{
private static final Map<ProcessNameSpaceEnum, Process> processCollections = new ConcurrentHashMap<>();
private ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
appContext = applicationContext;
}
@Override
public void afterPropertiesSet() {
// 将 Spring 容器中所有的 Payment 接口实现类注册到 processCollections
appContext.getBeansOfType(Categry.class)
.values()
.forEach(categry-> processCollections.put(categry.getType(), categry));
}
public static Categry getCategry(TypeEnum type) {
if (type== null) {
throw new IllegalArgumentException("type is empty.");
}
if (!processCollections.containsKey(type)) {
throw new IllegalArgumentException("type not supported.");
}
return processCollections.get(type);
}
}
4、客户端使用策略类
Categry aaa = xxxxManager.getCategry(type);
aaa.doProcess();
策略模式与SPI机制的区别
思想都类似,都是将后续的扩展与原来的代码隔离开来,从而避免新增代码对原有代码的影响
1、策略模式应用与同一个项目中代码层面,类层次,属于类级别的隔离
SPI机制更多的是链接不同项目,应用于框架级别,属于框架级别的隔离
2、SPI需要通过配置文件META-INF/services/xxx.yml下配置各个类的全限定类名
com.xxx.xxx.CategryA
com.xxx.xxx.CategryB
SPI获取类的方式
ServiceLoader.load(xxx.class);