暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

责任链模式在自定义业务对象场景中的应用

看点有用的 2021-10-24
589

业务需求


前一篇文章《矩阵的转置及在关系型数据库中的实践》中介绍了一种k-v存储的数据表结构(即AT表),这种数据表的应用场景为自定义业务对象。在该业务场景中,有一个需求是这样的:

在数据插入操作中,针对前端传过来的值,

  • 如果该属性配置了自动生成功能,则调用自动生成逻辑生成一个值替换前端传递的值进行存储,如订单号;

  • 否则,如果该属性值不为空,则将该属性值进行存储,如客户姓名;

  • 否则,如果该属性配置了默认值,则将配置的默认值作为该属性的值进行存储,如是否有效;

  • 否则,不进行任何处理。


上边的业务逻辑可以作为赋值操作进行统一封装,我们先看下常规操作代码是如何处理的。


常规操作模式


常规操作模式,即通过if…else…逻辑块进行处理,其代码示例如下所示。

// ① 调用自动生成方法,如果返回null表示非自动生成属性
Object value = DataProcess.getInstance().getDefaultValue(cfgFormField);
if (value == null){
    // ② 取前端传入值
if (jsonParam.containsKey(fieldCode)
&& StringUtils.isNotBlank(jsonParam.getString(fieldCode))) {
value = jsonParam.get(fieldCode);
    // ③ 前端未传值,取默认值
} else if (StrUtil.isNotBlank(cfgFormField.getDefaultValue())) { // 无前端传入,但有默认值
value = cfgFormField.getDefaultValue();
    // ④ 既无前端传入值,也无默认值,则不处理
else {
return;
}
}
复制


在这个示例中,通过if…else…实现了上述逻辑,如果有新业务逻辑的加入,则继续if…else…块的编写。考虑到代码的后期维护,显然这种实现方式是不符合要求的,违背了软件设计的开闭原则。那么就需要对这段代码进行改造,责任链模式是一个不错的选择。


责任链模式


上述代码的业务逻辑,说白了就是对value进行赋值,或者说清理,那么可以创建一个统一的值清理类DataValueCleaner,并定义一个静态方法clean,返回值为清理后的最终结果。


因为动态属性的赋值方案都封装在cfgFormField对象中,所以clean方法需要接受cfgFormField和前端传值。


DataValueCleaner类的实现如下所示。

public class DataValueCleaner {
/**
* 值清洗方法
* @param formField
* @param value
* @return
*/
public static Object clean(CfgFormField formField, Object value) {
        // TODO 数据处理逻辑
}
}
复制


接下来定义数据处理的统一接口ValueProcessor,该接口只有一个方法process,接收value入参,返回Object对象,该对象及经过处理后的value值。其实现如下所示。

public interface ValueProcessor {
/**
* 值处理方法
* @param formField
* @param value
* @return
*/
Object process(CfgFormField formField, Object value);
}
复制


该接口有三个实现类,AutoGenerateValueProcessor用于处理自动生成逻辑,OriginalValueProcessor用于原值处理,DefaultValueProcessor用于默认值处理。这三个实现类的具体逻辑与上述的① ② ③相同,此处不再赘述。至此,DataValueCleaner就可以细化代码逻辑进行责任链的封装,其具体实现如下所示。

public class DataValueCleaner {
/**
* 值处理链
*/
private static List<ValueProcessor> processorChain = new ArrayList<>();
static {
processorChain.add(new AutoGenerateValueProcessor());
processorChain.add(new OriginalValueProcessor());
        processorChain.add(new DefaultValueProcessor());
}


/**
* 值清洗方法
* @param formField
* @param value
* @return
*/
public static Object clean(CfgFormField formField, Object value) {
Object result = value;
for (ValueProcessor processor : processorChain) {
result = processor.process(formField, result);
}
return result;
}
}
复制


clean()方法中,通过循环来保证责任链中的每个处理逻辑都能够被执行到,如果某一个节点无处理逻辑,只需将value值return即可。在调用处,将上述的大段if…else…代码替换为如下一行语句,是不是更简洁了?

Object value = DataValueCleaner.clean(cfgFormField, jsonParam.get(fieldCode));
复制


业务逻辑扩展


如果在业务开发过程中,新增了业务逻辑,比如将时间属性的字段进行时间戳转换,那又该如何处理呢。

第一步,新建时间格式转换类,实现ValueProcessor接口并在process方法中编写业务逻辑;

第二步,在DataValueCleaner的责任链对象processorChain中添加第一步定义的类实例。


至此完成了业务逻辑的改造,通过责任链模式简化了代码结构、解耦了业务处理逻辑并提高了扩展性。

文章转载自看点有用的,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论