使用 Java 继承、泛型和函数式接口减少重复代码

1. 问题描述

有两个后台接口给前端返回统计数据,除了个别字段不一样外,其它字段是一样的,原来的代码每个接口定义各自返回的类,在Service方法中也是各自处理,因为处理的统计数据的逻辑基本相同,所以出现了很多重复代码。

2. 优化过程

2.1 通过继承减少重复字段定义

定义父类将两个返回类的公共字段放到父类中,不同的字段放到子类中。

父类 P:

@Getter
@Setter
public class P {
    private List<MonthStatDTO> monthStat = new ArrayList<>();

    private Long totalCount = 0L;    
}

@Getter
@Setter
public class MonthStatDTO {
    private String month;

    private Long count = 0L;    
}

子类 C1:

@Getter
@Setter
public class C1 extends P {
    private String name;

    public C1() {

    }

    public C1(StatQueryDTO data) {
        this.name = data.getId();
    }
}

子类 C2:

@Getter
@Setter
public class C2 extends P {
    private String id;
    
    private String type;  
    
    public C2() {

    }

    public C2(StatQueryDTO data) {
        this.id = data.getId();
        this.type = data.getType();
    }
}

子类中的有参数构造方法在后面说明。

2.2 通过泛型和函数式接口将处理逻辑封装为一个方法

数据处理过程中需要用到 List<C1>List<C2> , 可以通过泛型方法解决。

同时在数据处理过程中需要根据查询结果创建子类的对象,可以传入函数式接口参数 Function<StatQueryDTO, E> function ,同时在上面的子类中创建有参数的构造函数。

private <E extends P> void processDataStat(List<StatQueryDTO> statQueryDTOS,List<E> result, Function<StatQueryDTO, E> function) {    
        Map<String, Integer> indexMap = new HashMap<>();
        for (statQueryDTOS item : statQueryDTOS) {
            MonthStatDTO monthStat = new MonthStatDTO();
            monthStat.setMonth(item.getMonth());
            if (indexMap.containsKey(item.getId())) {
                E existedDTO = result.get(indexMap.get(item.getQueryTypeId()));
                Long total = item.getCount() + existedDTO.getTotalCount();
                monthStat.setCount(total);
                existedDTO.getMonthStat().add(monthStat);
                existedDTO.setTotalCount(total);
            } else {
                monthStat.setCount(item.getCount());
                E newDTO = function.apply(item);
                newDTO.getMonthStat().add(monthStat);
                newDTO.setTotalCount(monthStat.getCount());
                result.add(newDTO);
                indexMap.put(item.getId(), result.size() - 1);
            }
        }
    }

在两个接口的 Service 方法中调用处理方法

Service 方法1:

...
List<C1> result = new ArrayList<>();
processDataStat(statQueryDTOS, result, C1::new);
...

Service 方法2:

...
List<C2> result = new ArrayList<>();
processDataStat(statQueryDTOS, result, C2::new);
...

总结

通过使用继承、泛型、函数式接口减少了重复代码,提高代码的复用度,有助于后续代码维护和扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值