转换器模式
在实际开发中,不管是三层架构还是DDD都会涉及对象的转换,比如xxxRequest转成xxxDTO,xxxDTO转成xxxDO等。目前最优雅的转换方式我称为转换器模式(Converter)
转换器模式主要用于在不同类型的对象之间进行转换,它的好处在于可以提高代码的可读性和可维护性,同时也有助于减少代码重复,提高代码复用性。
转换器模式的好处
- 单一职责原则:每一个Converter应该只负责一种类型的转换,比如GoodsConverter,OrderConverter
- 复用性:一大坨的set方法再也看不见了
- 可读性:Converter代码应该只有赋值的操作,清晰易读,不要有大量的计算逻辑
转换器定义为接口还是类
如果转换逻辑比较简单,且不需要状态,可以选择定义为接口,并提供默认方法。如果转换逻辑复杂,或者需要维护状态,可以选择定义为类。这里的状态通常指的是转换器中是否需要维护一些信息。
最佳实践
这里以DTO转为DO为例
DTO,DO
@Data
@Builder
public class UserDTO {
private Long id;
private String username;
private String email;
}
@Data
@Builder
public class UserDO {
private Long userId;
private String userName;
private String userEmail;
}
UserConverter
所有跟User相关的实体类转换都在这个转换器里
public class DTOToDOConverter {
public static UserDO convert(UserDTO userDTO) {
if (userDTO == null) {
return null;
}
UserDO userDO = new UserDO();
userDO.setUserId(userDTO.getId());
userDO.setUserName(userDTO.getUsername());
userDO.setUserEmail(userDTO.getEmail());
return userDO;
}
}
这里的转换器提供了一个静态方法,至于方法内UserDTO转换为UserDO的方式根据个人喜好即可。可以new对象然后依次set,也可以用@Builder方法来创建对象,也可以链式调用。需要注意的是这里面不要有太多的逻辑。
使用案例
public class Main {
public static void main(String[] args) {
UserDTO userDTO = new UserDTO();
userDTO.setId(1L);
userDTO.setUsername("Alice");
userDTO.setEmail("alice@example.com");
UserDO userDO = DTOToDOConverter.convert(userDTO);
System.out.println("转换后的UserDO: " + userDO);
}
}
进阶用法
这里不具体展开,如果公司用到就用,公司没用到尽量不要往pom里面加。当团队规范与个人习惯冲突时尽量以团队规范为准。进阶的用法需要引入mapstruct的依赖。依赖如下:
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
使用时在Converter上增加@Mapper注解即可,注意这不是Spring中的注解,看下下面示例代码的import
import com.jayden.user.entity.dto.SysUserDto;
import com.jayden.user.entity.req.SysUserReq;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author jayden
*/
@Mapper
public interface SysUserDtoConvert {
SysUserDtoConvert INSTANCE = Mappers.getMapper(SysUserDtoConvert.class);
SysUserDto convertReqToDto(SysUserReq sysUserReq);
}