根据不同业务需求实现灵活可配置操作类
业务描述
现有一系统,主要负责审核各种不同类型的单据,根据单据类型执行不同的操作,与不同的外围系统交互,而且单据类型十分繁多,可细分至几十种。如果所有的操作都写死在一个类里面去完成,那么这个类势必会变得十分臃肿,难以维护,而且也不够灵活。万一某种单据的需要从一种逻辑,改变为另一种逻辑,修改起来就比较麻烦。
设计思路
为了实现可配置,可扩展的目的,我们考虑使用可配置操作类的方式:
- 根据不同单据类型,配置不同的操作类;
- 也可以根据操作逻辑划分,同一类逻辑的单据使用同一个操作类。
- 有新增的单据,可以新增操作类,不必修改之前的类
示例demo
(一)定义接口
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-09-11 16:27
* @desc : 定义接口,需要执行的抽象方法
*/
public interface AbstractMethod {
void execute(Map<String, Object> var1);
}
(二)定义抽象类
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-09-11 15:55
* @desc : 执行操作的抽象类,所有配置的具体执行类都需要继承此类
*/
public abstract class AbstractAction implements AbstractMethod{
//可以在此处执行一些通用的操作
}
(三)调用抽象类的方法,执行具体操作
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-09-11 16:00
* @desc : 调用抽象类的方法,执行具体操作
*/
@Slf4j
@Component
public class DoAction {
@Autowired
private ApplicationContext context;
public void startAction(Map<String,Object> args){
AbstractAction abstractAction = null;
//方式一:根据配置来灵活获取的完整类名,
// String clazzName = (String)args.get("className");
//方式二:传入实体类,利用反射,直获取类名,【相比方式1可省去配置,但灵活性较低,可根据业务需求选择】
Class clazz =args.get("actionDto").getClass();
String clazzName = clazz.getName();
try {
abstractAction = (AbstractAction)this.context.getBean(Class.forName(clazzName));
} catch (ClassNotFoundException e) {
log.error("获取操作类错误:{}",e);
e.printStackTrace();
}
abstractAction.execute(args);
}
}
(四)实际操作类
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-09-11 16:01
* @desc : 实现了抽象类的,实际操作类
*/
@Slf4j
@Component
public class Action extends AbstractAction {
@Override
public void execute(Map<String, Object> args) {
log.info("action获取到传入的单据编号:[{}]", args.get("billCode") );
log.info("执行后置操作类!");
}
}
(五)测试使用
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-09-11 17:10
* @desc : 测试使用
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class TestActionTest {
@Autowired
public DoAction doAction;
@Autowired
public Action action;
@Test
public void dosth(){
Map<String,Object> args = new HashMap<>();
//可以在界面上根据单据类型配置不同的操作类名,将类名存入数据库,
//此处类名根据单据类型从数据库获取,从而实现不同单据执行不同操作的目的
args.put("className","com.lx.soil.demos.AfterAction.Action");
args.put("billCode","13701-XX-201809120001");
args.put("actionDto",action);
doAction.startAction(args);
}
}