前言
日常开发中,我们经常会遇到一些重复冗余的代码,大家都知道重复冗余都有这些缺点:可维护性差、可读性差、增加错误风险等等,本文章总结了几种解决冗余代码的方法
第一种:抽取公用方法
案例:我们将英文名字转换成大写和小写并进行输出
优化前代码:
public static void main(String[] args) { List<String> names = Arrays.asList("ZhangSan","LiSi","WangWu","ZhaoLiu","XuQi"); System.out.println("转换为大写:"); for (String name:names ) { String upperCaseName = name.toUpperCase(); System.out.println(upperCaseName); } System.out.println("转换为小写:"); for (String name:names ) { String lowerCaseName = name.toLowerCase(); System.out.println(lowerCaseName); } }
我们可以把大小写的控制抽取成用function函数式去传进来
优化后代码:
public static void processNames(List<String> names, Function<String,String> nameProcessor,String processType){ System.out.println(processType + "Names:"); for (String name:names ) { String processordName = nameProcessor.apply(name); System.out.println(processordName); } } public static void main(String[] args) { List<String> names = Arrays.asList("ZhangSan","LiSi","WangWu","ZhaoLiu","XuQi"); processNames(names,String::toUpperCase,"转换为大写"); processNames(names,String::toLowerCase,"转换为小写"); }
第二种:抽取为工具类
如果代码有很多共性,比如说注册、修改邮箱、邮箱登录等都需要校验邮箱的方法,这时候就可以把校验邮箱的方法抽出来成为一个工具类。
public class EmailValidatorUtil { private static final String EMAIL_REGEX = "^[A-Za-z0-9+_.-]+@(.+)$"; private static final Pattern pattern = Pattern.compile(EMAIL_REGEX); public static boolean isValid(String email) { Matcher matcher = pattern.matcher(email); return matcher.matches(); } } //注册的代码可以简化为这样啦 public class RegisterServiceImpl implements RegisterService{ public boolean registerUser(UserInfoReq userInfo) { if (!EmailValidatorUtil.isValid(userInfo.getEmail())) { System.out.println("Invalid email address."); return false; } // 进行其他用户注册逻辑,比如保存用户信息到数据库等 // 返回注册结果 return true; } }
第三种:反射
在日常开发中我们经常会遇到PO、DTO、VO的转换,例如:
public UserVo conevert(UserPo userPo){ UserVo userVo = new UserVo(); userVo.setName(userPo.getName()); userVo.setSex(userPo.getSex()); userVo.setAge(userPo.getAge()); return userVo; }
我们可以用到BeanUtils.copyProperties()来进行优化,BeanUtils.copyProperties()
底层就是使用了反射:
public UserVo conevert2(UserPo userPo){ UserVo userVo = new UserVo(); BeanUtils.copyProperties(userPo,userVo); return userVo; }
这里科普一个小知识点:
PO、DTO、VO是软件开发中常见的三个设计模式。它们分别代表持久对象(Persistent Object)、数据传输对象(Data Transfer Object)和值对象(Value Object)。
- 持久对象(PO):
持久对象是指与数据库表或其他持久化机制中的数据一一对应的对象。它们通常与数据库表格的结构相对应,用于在应用程序和数据库之间进行数据的转换和传递。PO 中包含了持久化层(如 ORM 框架)所需的一些注解或配置信息。PO 一般由持久层框架自动生成和维护。 - 数据传输对象(DTO):
数据传输对象是用于在不同层之间传输数据的对象。DTO 主要用于层间数据的传递,将数据从一层传递到另一层,可以批量传输多个数据对象,以减少网络通信的开销。DTO 通常包含与业务相关的属性,可以被多个服务或组件使用。 - 值对象(VO):
值对象是不可变的对象,它具有值语义,主要用于封装一组相关的数据,用于传递和管理数据。VO 通常是以领域驱动设计为基础的一种设计模式,用于表示领域中的概念对象。VO 对象在不同业务逻辑之间传递,能够保证数据的完整性和一致性。
这三个设计模式的区别如下:
- PO 是与数据库表格一一对应的对象,用于在应用程序和数据库之间进行数据的转换和传递。
- DTO 是用于不同层之间传输数据的对象,主要用于减少网络通信的开销。
- VO 是不可变的值对象,用于传递和管理数据,并保证数据的完整性和一致性。
应用场景:
- PO 主要应用于持久层,与数据库进行数据交互。
- DTO 主要应用于服务层或接口之间,用于在不同层之间传输数据。
- VO 主要应用于领域模型或业务逻辑中,用于封装概念对象并传递数据。
第四种:泛型
泛型是如何去除重复代码的呢?给大家看个例子,我有个转账明细和转账余额对比的业务需求,有两个类似这样的方法:
private void getAndUpdateBalanceResultMap(String key, Map<String, List<TransferBalanceDTO>> compareResultListMap, List<TransferBalanceDTO> balanceDTOs) { List<TransferBalanceDTO> tempList = compareResultListMap.getOrDefault(key, new ArrayList<>()); tempList.addAll(balanceDTOs); compareResultListMap.put(key, tempList); } private void getAndUpdateDetailResultMap(String key, Map<String, List<TransferDetailDTO>> compareResultListMap, List<TransferDetailDTO> detailDTOS) { List<TransferDetailDTO> tempList = compareResultListMap.getOrDefault(key, new ArrayList<>()); tempList.addAll(detailDTOS); compareResultListMap.put(key, tempList); }
这两块代码,流程功能看着很像,但是就是不能直接合并抽取一个公用方法,因为类型不一致。单纯类型不一样的话,我们可以结合泛型处理,因为泛型的本质就是参数化类型.优化为这样:
private <T> void getAndUpdateResultMap(String key, Map<String, List<T>> compareResultListMap, List<T> accountingDTOS) { List<T> tempList = compareResultListMap.getOrDefault(key, new ArrayList<>()); tempList.addAll(accountingDTOS); compareResultListMap.put(key, tempList); }
文章评论