Java 函数式编程

声明式编程(Declarative Programming)是一种编程风格,我们说明想要完成什么(what),而不是指明怎么做(how)。 --《On Java》
与之相对的是命令式编程(Imperative Programming),后者关注具体的步骤和操作顺序。声明式编程通常更简洁、更易于理解和维护。

Java 8 引入了新特性:
● 函数式编程:包括Lambda 表达式、函数式接口、方法引用等
● 接口默认方法和静态方法:增强接口的功能,支持函数式编程。
Stream API、Optional 提高了代码的简洁性和可读性,开发中用的比较多。
但是 Javaer 常常忽略了函数式编程带来的影响或者它的作用,也就是代码风格的改变。这里抛砖引玉,不讲原理,直讲开发的中的改变。

Java 8 提供了一些常用的内置函数式接口:
● Function<T, R>:接受一个参数,返回一个结果。
● Predicate:接受一个参数,返回一个布尔值。
● Supplier:不接受参数,返回一个结果。
● Consumer:接受一个参数,不返回结果。

一、命令式编程

在web编程里,良好的编程习惯式不能把底层的实体类(DO)直接返回给请求接口,常常涉及到一些类型转换。
JDK 8 之前类型转换一般有几种做法:
● 类型直接写在业务代码里
● 把类型转换代码放到 private 方法里
● 把类型转换代码放到一个类型转换类中
这样做的缺点:
● 可读性差:代码冗长,不适合给代码审核人员/其他开发快速了解业务逻辑

 public void saveTask(WarningTaskAddCriteria req) {
    // 存储预警任务基本信息
    SysWarningTaskEntity taskEntity = new SysWarningTaskEntity()
            .setWarningEventId(req.getTaskEventInfo().getWarningEventId())
            .setWarningEventName(req.getTaskEventInfo().getWarningEventName())
            .setTaskStatus(TaskStatus.SAVED.getCode())
            .setAddAttributes();
    BeanUtils.copyProperties(req,taskEntity);
    final int taskInsertAffectedRows = taskMapper.insert(taskEntity);
    // 省略其他操作
}

二、声明式(函数式)编程

函数式接口可以作为参数、返回结果,也可以组合使用。
举个简单的例子 类型转化类 。个人习惯是封装一层,团队统一代码风格。

类型转化类:

import java.util.function.Function;

public class TypeConverter {
    public static <T, R> R convert(T t, Function<T, R> function) {
        if (t == null || function == null) {
            throw new IllegalArgumentException("Arguments cannot be null");
        }
        return function.apply(t);
    }
}

改造后的代码:

public void saveTask(WarningTaskAddCriteria req) {
        // 存储预警任务基本信息
        SysWarningTaskEntity taskEntity = TypeConverter.convert(req.getTaskEventInfo(), info -> {
            SysWarningTaskEntity entity = new SysWarningTaskEntity()
                    .setWarningEventId(info.getWarningEventId())
                    .setWarningEventName(info.getWarningEventName())
                    .setTaskStatus(TaskStatus.SAVED.getCode())
                    .setAddAttributes();
            SpringBeanUtils.copyProperties(req, entity);
            return entity;
        });

        final int taskInsertAffectedRows = taskMapper.insert(taskEntity);
        // 省略其他操作
}

// 更极端一些
public void saveTask(WarningTaskAddCriteria req) {
    // 存储预警任务基本信息
    final int taskInsertAffectedRows = taskMapper.insert(TypeConverter.convert(req.getTaskEventInfo(), info -> {
        SysWarningTaskEntity entity = new SysWarningTaskEntity()
                .setWarningEventId(info.getWarningEventId())
                .setWarningEventName(info.getWarningEventName())
                .setTaskStatus(TaskStatus.SAVED.getCode())
                .setAddAttributes();
        SpringBeanUtils.copyProperties(req, entity);
        return entity;
    }));
    // 省略其他操作
}

改造后的优点:
● 可读性更强:虽然代码看起来只是放到不同的地方,但是 其他开发人员看到 TypeConverter.convert就会明白这个是要做什么(what) 而不是 怎么做(how)。
● 更易于维护:在实际工作中见到过太多情况,前面声明一个类,然后后面的代码又对这个对象进行更改。一般来讲 final 的对象更加安全可靠。

三、风格改变会有什么影响吗?

3.1 事务是否会有影响?

答案是不会有影响。

@Transactional
public void saveTask(WarningTaskAddCriteria req) {
    SysWarningTaskEntity taskEntity = new SysWarningTaskEntity()
        .setWarningEventId(req.getTaskEventInfo().getWarningEventId())
        .setWarningEventName(req.getTaskEventInfo().getWarningEventName())
        .setTaskStatus(TaskStatus.SAVED.getCode())
        .setAddAttributes();
    BeanUtils.copyProperties(req, taskEntity);

    // 这里仅仅是为了演示,没必要这么写
    Consumer<SysWarningTaskEntity> save = entity -> {
        taskMapper.insert(entity);
    };
    save.accept(taskEntity);

    // 强制抛出异常测试回滚
    throw new RuntimeException("Test rollback");
}

四、函数式例子

4.1 链式函数调用

public JobDetails findJobById(String jobId) {
    // 查询任务基础信息
    Function<String,JobDetails> queryJobBaseInfo = id -> {
        JobDetails jobDetails = new JobDetails();
        final SysWarningJobEntity jobBaseInfo = jobMapper.selectById(id);
        jobDetails.setJobGroupId(jobBaseInfo.getJobGroup());
        BeanUtils.copyProperties(jobBaseInfo,jobDetails);
        return jobDetails;
    };

    // 查询任务参数信息
    Function<JobDetails, JobDetails> queryJobParams = jobDetails -> {
        LambdaQueryWrapper<SysWarningJobParamEntity> wrapper = WrapperUtil.createQueryWrapper(SysWarningJobParamEntity.class)
                .eq(SysWarningJobParamEntity::getJobId,jobDetails.getId());
        final List<WarningJobParamDTO> jobParams = jobParamMapper.selectList(wrapper).stream().map(paramEntity -> {
            WarningJobParamDTO jobParamDTO = new WarningJobParamDTO();
            BeanUtils.copyProperties(paramEntity, jobParamDTO);
            return jobParamDTO;
        }).collect(Collectors.toList());
        jobDetails.setJobParams(jobParams);
        return jobDetails;
    };

    // 查询模板变量信息
    Function<JobDetails, JobDetails> queryTemplateVariables = jobDetails -> {
        LambdaQueryWrapper<SysWarningJobPlaceholderConfigEntity> wrapper = WrapperUtil.createQueryWrapper(SysWarningJobPlaceholderConfigEntity.class)
                .eq(SysWarningJobPlaceholderConfigEntity::getJobId, jobDetails.getId());
        final List<JobTemplateVariable> jobTemplateVariables = placeholderConfigMapper.selectList(wrapper).stream().map(entity -> {
            JobTemplateVariable variable = new JobTemplateVariable();
            variable.setVariableCode(entity.getPlaceholderCode());
            variable.setVariableName(entity.getPlaceholderName());
            variable.setVariableType(entity.getType());
            return variable;
        }).collect(Collectors.toList());
        jobDetails.setJobTemplateVariables(jobTemplateVariables);
        return jobDetails;
    };
   
    // 使用链式调用
    return queryJobBaseInfo
            .andThen(queryJobParams)
            .andThen(queryTemplateVariables)
            .apply(jobId);
}


public void delete(String jobId) {
    // 删除任务
    Consumer<String> deleteJob = id -> {
        SysWarningJobEntity jobEntity = new SysWarningJobEntity().setDeleteAttributesWithPrimaryKey(id);
        jobMapper.updateById(jobEntity);
    };
    //删除 任务参数
    Consumer<String> deleteJobParam = id -> {
        LambdaUpdateWrapper<SysWarningJobParamEntity> wrapper = WrapperUtil.createDeleteWrapper(SysWarningJobParamEntity.class)
                .eq(SysWarningJobParamEntity::getJobId, id);
        jobParamMapper.update(wrapper);
    };
    //删除 任务模版变量
    Consumer<String> deleteJobTemplateVar = id -> {
        LambdaUpdateWrapper<SysWarningJobPlaceholderConfigEntity> wrapper = WrapperUtil.createDeleteWrapper(SysWarningJobPlaceholderConfigEntity.class)
                .eq(SysWarningJobPlaceholderConfigEntity::getJobId, id);
        placeholderConfigMapper.update(wrapper);
    };
    deleteJob.andThen(deleteJobParam).andThen(deleteJobTemplateVar).accept(jobId);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值