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);
...
总结
通过使用继承、泛型、函数式接口减少了重复代码,提高代码的复用度,有助于后续代码维护和扩展。
1792

被折叠的 条评论
为什么被折叠?



