java反射之前接触比较多,但仅技术方面思考的多;这次主要是从业务角度出发,思考java反射在业务模块设计中如何发挥更高效的作用,以提高生产率
。
1.业务需求
要处理银行回单票据,提取出付款人、收款人及对应银行和业务信息,每个银行的格式都不统一。所以需要对各家银行的格式进行预处理,规整为标准格式后,交由后续模块处理。
这个预处理格式化的设计有多种
2.方案选型
做法 | 适用场景 | 技能要求 |
---|---|---|
在if..else中添加分支逻辑 | 适用于分支较少的场景,如只有2~4个 | 简单 |
把分支逻辑提取为句柄,显示注册到句柄map或list中 | 实用于分支较多场景,但变化不大;否则若经常变动,注册时容易漏掉 | 需要有一定的业务抽象和接口设计能力 |
把分支逻辑提取为句柄,通过反射自动注册到map或list中 | 实用于分支较多场景,也满足经常变动场景 | 抽象能力+java反射技术 |
注册到list? | 分支判断逻辑复杂,只能采用低效的遍历判断 | |
还是注册到map? | 分支判断逻辑清晰,特别是存在关键词区分 |
3.采用反射的技术方案
我们这个场景的特点:
- 分支判断逻辑非常清晰,就是根据每家银行的回单类型进行分支判断。
- 并且不断有新类型会增加进来。
所以采用下面做法
3.1.抽象Formater接口,通过Map管理所有接口
public static HashMap<String,Formater> formaterMap = new HashMap<String,Formater>();
public interface Formater {
void format(Resource resource);
}
3.2.通过java反射自动注册
- 获得所有实现类(用到了Reflections,这是一个开源工程,在github上有源码)
- 实例化(如果是内部类,要特别注意实例化方法,可参考使用new和反射产生java内部类的实例化对象)
- 注册到map中
static {
Reflections reflections = new Reflections("prepare");//包名,可以降低搜索范围
Set<Class<? extends Formater>> subTypes = reflections
.getSubTypesOf(Formater.class);
for (Class<? extends Formater> clazz : subTypes) {
String typeName = clazz.getTypeName();
int idx = typeName.lastIndexOf("$");//内部类场景
int idx1 = typeName.lastIndexOf(".");
if(idx<idx1)idx = idx1;
String className = typeName.substring(idx+1);//提取类名,作为主键
try {
formaterMap.put(className, clazz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.3.应用模块调用简洁
//对银行回单进行预处理
Formater formater = PrepareModule.formaterMap.get(resource.getResourceType());
if(formater != null)
formater.format(resource);
//do next....
3.4.扩展分支简单且不会出错
以后扩展也比较简单,只需要增加新的方法实现类即可,不必担心漏掉注册的问题。
static public class ChinaBankReceiptFormater implements Formater {
@Override
public void format(Resource resource) {
//TODO
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-25 19:25:38