看下面一段代码.
if (type == 3000) {
...
} else if (type == 3001){
...
} else if (type == 3002){
...
} else {
...
}
这种代码有什么问题吗啊?
- 代码看上就很low,比这个高级点的就是switch case了
- 如果要增加一个type怎么办?
- 增加一个if分支
- 增加一个相应分支的处理方式
- 分支代码和处理代码分散在不同区域,维护困难。
比较优雅的代码应该如下:
@UnitType(3000)
public class ExecProcessUnit extends ExecBaseProcessUnit {
@Override
protected Object exec(ProcessContext ctx) {
XXXXXXXX
}
}
增加一个注解即可优雅的完成。
怎样做到这种方式的呢?
- 首先需要一个@UnitType注解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface UnitType {
int value() default 0;
}
- 需要一个能解析这些注解的类,并且可以开机扫描
@Slf4j
@Component
@Lazy(false)
public class ProcessUnitManager {
private static final String PROC_UNIT_PACKAGE ="com.tbkk.xxxx.procunit.impl";
private static Map<int, ExecBaseProcessUnit> unitMap = new ConcurrentHashMap<>();
/**
*
* scan 处理单元类型和处理单元组件类型
*
**/
@PostConstruct
private void initScanProcUnit() {
Set<Class<?>> classes = ClassScanerUtils.scan(PROC_UNIT_PACKAGE, UnitType.class, Component.class);
for(Class clazz : classes) {
UnitType [] unitTypes = (UnitType []) clazz.getAnnotationsByType(UnitType.class);
Arrays.stream(unitTypes).forEach( unitType->
{
unitMap.put(unitType.value(), (ExecBaseProcessUnit)springBeanUtils.getBean(clazz));
}
);
}
}
}
- 需要一个能定位到这些处理类的动作,指定类进行处理,如下: ``` java
ProcessUnitManager.getUnitMap().get(type).exec(ctx);
```
- 以后如果有额外的type出现,在相应的包下面增加处理单元即可。
策略模式和SPI的区别
如果从代码接入的级别来看,策略模式还是在原有项目中进行代码修改,只不过它不会修改原有类中的代码,而是新建了一个类。而 SPI 机制则是不会修改原有项目中的代码,其会新建一个项目,最终以 Jar 包引入的方式代码。
从这一点来看,无论策略模式还是 SPI 机制,他们都是将修改与原来的代码隔离开来,从而避免新增代码对原有代码的影响。但策略模式是类层次上的隔离,而 SPI 机制则是项目框架级别的隔离。
从应用领域来说,策略模式更多应用在业务领域,即业务代码书写以及业务代码重构。而 SPI 机制更多则是用于框架的设计领域,通过 SPI 机制提供的灵活性,让框架拥有良好的插件特性,便于扩展。
附 :想了解SPI的可以看我的另外一篇文章【深入理解SPI】