需求:
制作一个表单,根据主表的下拉框显示对应的 明细内容,根据明细的勾选选择是否下推到erp中去。
**
思考1:设计表单时候,怎么根据下拉框选择出现不同的明细行?
设计思路:
设计好所有的明细表,通过下拉绑定事件确定明细表的展示,展示的时候显示对应的数据,下拉框更改的情况,要清空之前的数据。对应 明细不存在任何数据的情况下,需要抛出错误,流程无法保存。
前端设计如下,说干就干,直接到下一步后端代码的设计。
思考2:数据封装的问题
众所周知,泛微oa接口数据流转集成,是需要在某个流程执行保存后再执行的,此时,我需要的是一个接口,对应执行9个明细方法,
我需要设计一个通用的方法解决这些数据封装的问题!
解决方案:策略工厂模式
1、策略工厂方法设计 :
(1) 设计一个工厂 StrategyFactory;
(2) 设计一个执行策略接口Strategy类;
(3) 9个对应的明细表实现Strategy中的execute 方法,处理自己的数据;
(4)在StrategyFactory 中定义方法,将9个策略注册到map中去,定义 getStrategyById(String id)方法;
(5) 设计9个明细对应的实体类;
(6)工厂中执行 Strategy execute(RequestInfo requestinfo)方法;
2、执行:
// 获取到对应的策略(需要注意,此时id为null或者strategy未找到的情况)
(1)Strategy strategy = StrategyFactory.getStrategyById(id);
// 根据策略执行对应的方法
(2)String result= strategy.execute(requestinfo);
// 打印结果是否一致
(3)System.out.println("result="+result);
问题:
策略中(4)步骤这个存在大量的if else情况,一点也不优雅,写java追求的就是优雅!!!
解决方案:枚举
将工厂类设计成枚举的方式,在设计枚举的时候写入对应的class类(实现了strategy接口),同样可以调用execute方法
(1)设计一个枚举类,存储9个明细流程对应的信息SkipEnum,
(2)属性:id,desc(描述),paramClass(对应的策略类 ? extends Strategy)
(3)创建一个方法SkipEnum getByIndex(int id);
// 方法可以用流的方式写
public static SkipEnum getById(int index){
return Arrays.stream(values())
.filter(item-> item.getId()==index)
.findAny()
.orElse(null);
}
(4) 改造上述执行方案:
SkipEnum skipEnum = SkipEnum.getById(id);
String result = skipEnum.getParamClass().execute(requestinfo);
枚举真是个好东西啊!
思考3:通用简化和优雅
上述做法看上去没什么问题,但是在详细编写的时候,会存在策略类中只有一两行代码,但是这个类必须存在;
例如: 物料明细和客户新增这两个数据处理策略都是一样,只是实体类不一样,那这样就会出现一个类中有只有类的替换操作,看起来实在是不美观,而且多了很多冗余的类
为了追求优雅,怎么再次简化!!
解决方案:Function函数式接口处理返回对应的类
方法选用: 有四种方式
1、Function:适合接收参数并且有返回(1到2个参数),apply()
2、Consumer:适合接收参数无返回值(1到2个参数),accept()
3、Predicate: 适合接收参数,调用执行链,返回一个boolean类型的值(需要注意链路 and or) test()
4、Supplier:无参数,直接返回结果值(无偿提供的店家哈哈哈哈哈),get()
派生的 Operator,基本不咋用,了解就好
这里采用的BiFunction<T,U, T> 第一个T为参数类T,第二个为参数U,第三个为返回T;
实例代码:
// 通用实体类封装
public static <T extends IErpModel> List<T> buildCommonModelList(
DetailTable detailTable,Class<T> clazz,BiFunction<T, Row, T> modelFunction
) {
List<T> resultList = Arrays.stream(detailTable.getRow()).map(row -> {
// 不做操作的时候,传入为空
if (modelFunction == null) {
return isNeedPush ? t : null;
}
return modelFunction.apply(t, row);
})
return resultList;
}
// 具体到某个类 处理对应的类 row为明细行数据,model为传入实体
private BiFunction<MaterialModel, Row, MaterialModel> buildMaterialModel() {
return (model, row) -> {
String rowId = row.getId();
model.setDetail_id(rowId);
log.info("实体类t:" + model);
return model;
};
}
需注意:
在泛微e8中,switch判断类型为枚举的时候,代码将不会继续被执行!!! 老老实实使用if else判断!!!