Jdk8之Function场景应用

文章目录

  • 1.场景再现
  • 2.Function

日常编程中,如果使用Idea时总会遇到破浪线的代码块,鼠标悬浮上去,提示Found Duplicated Code in XXX。从代码设计的角度来讲,不符合DRY(Don't Repeat Yourself)原则。那我们又如何改善你眼前看到的一切呢?对于大多数同学来讲,肯定视而不见;但对于那么一丢丢同学来讲,却无法接受这样的代码,总想重构一下。

1.场景再现

/**
     * 分页查出当前资金方绑定产品列表
     * @param form
     * @return
     */
    @LogMonitor("资金方管理")
    public Result<PageVO<ProductVo>> loadBindRecords(PageForm<FundProductForm> form) {
        List<ProductVo> productVos = Collections.emptyList();
        int count = 0;
        try {
            List<Product> products = fundProductService.selectBindProductByParams(form);
            if (CollectionUtils.isEmpty(products)) {
                return Result.failInEmptyRecord(null);
            }
            Map<String, String> productTypeMap = diamondConfigProxy.queryProductType().stream().collect(Collectors.toMap(ProductTypeRe::getCode, ProductTypeRe::getName));
            productVos = new ProductVoConvertor().convertList(products, productTypeMap);
            count = fundProductService.getBindProductCount(form);
        }catch (Exception e){
            LOGGER.error("{}loadBindRecords加载数据异常,form={}",LOG_TITLE, JSON.toJSON(form),e);
            return  Result.fail(PageVO.newInstance(count,productVos));
        }
        return Result.suc(PageVO.newInstance(count,productVos));
    }

    /**
     * 分页查出当前资金方尚未绑定产品列表
     * @param form
     * @return
     */
    @LogMonitor("资金方管理")
    public Result<PageVO<ProductVo>> loadNotBindRecords(PageForm<FundProductForm> form) {
        List<ProductVo> productVos = Collections.emptyList();
        int count = 0;
        try {
            List<Product> products = fundProductService.selectNotBindProductByParams(form);
            if (CollectionUtils.isEmpty(products)) {
                return Result.failInEmptyRecord(null);
            }
            Map<String, String> productTypeMap = diamondConfigProxy.queryProductType().stream().collect(Collectors.toMap(ProductTypeRe::getCode, ProductTypeRe::getName));
            productVos = new ProductVoConvertor().convertList(products, productTypeMap);
            count = fundProductService.getNotBindProductCount(form);
        }catch (Exception e){
            LOGGER.error("{}loadNotBindRecords加载数据异常,form={}",LOG_TITLE, JSON.toJSON(form),e);
            return  Result.fail(PageVO.newInstance(count,productVos));
        }
        return Result.suc(PageVO.newInstance(count,productVos));
    }

上面就是个方法,发现方法体中大部分代码几乎一样的,鼠标悬浮上去提示如下:

我们分析上述两个方法,得知什么结论呢?

  • 1、方法入参一致。
  • 2、方法返回参数一致。
  • 3、方法体处理逻辑几乎一致,唯一区别就是调用 fundProductService.selectXXX 这句代码。

2.Function

该函数是jdk8新出来的,用于实现函数式编程。如果它没有出现,传统逻辑,我们就需要自己定义一个接口,调用时,并实现这个接口。它的出现,则无需我们重复定义。

2.1 源码

/**
 * Represents a function that accepts one argument and produces a result.
 *
 * 

This is a functional interface * whose functional method is {@link #apply(Object)}. * * @param the type of the input to the function * @param the type of the result of the function * * @since 1.8 */ @FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); // 省略其他代码 }

看到上述代码,我们会发现内置了一个R apply(T t),什么意思呢?

Applies this function to the given argument. (给定参数T 调用该函数返回R)

2.2 结合

既然Function可以允许我们自定一个函数,通过给定参数T返回结果R 那么,对应案例中,就是给定参数PageForm form,返回结果Result>。我们顺着这个思路,把上述代码,差异的部分提取一个函数,代码如下:

public Result<PageVO<ProductVo>> loadRecords(PageForm<FundProductForm> form, Function<PageForm<FundProductForm>,List<Product>> query) {
        List<ProductVo> productVos = Collections.emptyList();
        int count = 0;
        try {
            List<Product> products = query.apply(form);
            if (CollectionUtils.isEmpty(products)) {
                return Result.failInEmptyRecord(null);
            }
            Map<String, String> productTypeMap = diamondConfigProxy.queryProductType().stream().collect(Collectors.toMap(ProductTypeRe::getCode, ProductTypeRe::getName));
            productVos = new ProductVoConvertor().convertList(products, productTypeMap);
            count = fundProductService.getNotBindProductCount(form);
        }catch (Exception e){
            LOGGER.error("{}loadNotBindRecords加载数据异常,form={}",LOG_TITLE, JSON.toJSON(form),e);
            return  Result.fail(PageVO.newInstance(count,productVos));
        }
        return Result.suc(PageVO.newInstance(count,productVos));
    }

那么原先调用的方法,则修改如下:

/**
     * 分页查出当前资金方绑定产品列表
     * @param form
     * @return
     */
    @LogMonitor("资金方管理")
    public Result<PageVO<ProductVo>> loadBindRecords(PageForm<FundProductForm> form) {
        return loadRecords(form, arg -> fundProductService.selectBindProductByParams(form));
    }

    /**
     * 分页查出当前资金方尚未绑定产品列表
     * @param form
     * @return
     */
    @LogMonitor("资金方管理")
    public Result<PageVO<ProductVo>> loadNotBindRecords(PageForm<FundProductForm> form) {
        return loadRecords(form, arg -> fundProductService.selectNotBindProductByParams(form));
    }

是不是很简单,代码瞬间看起来清新了许多。

3.总结

Function 函数通畅用于封装一个通用的函数,对于参数传入的参数T,返回结果R。对于日常中如果代码中只是调用一个函数的差异,比如查询数据库结果集是调用不同的接口,则可以通过它来实现封装。

下面的是我的公众号二维码图片,欢迎关注。
Jdk8之Function场景应用_第1张图片

你可能感兴趣的:(设计模式活用)