--- layout: pattern title: Converter folder: converter permalink: /patterns/converter/ categories: Creational language: zh tags: - Decoupling --- ## 目的 转换器模式的目的是提供相应类型之间双向转换的通用方法,允许进行干净的实现,而类型之间无需相互了解。此外,Converter模式引入了双向集合映射,从而将样板代码减少到最少。 ## 解释 真实世界例子 > 在真实的应用中经常有这种情况,数据库层包含需要被转换成业务逻辑层DTO来使用的实体。对于潜在的大量类进行类似的映射,我们需要一种通用的方法来实现这一点。 通俗的说 > 转换器模式让一个类的实例映射成另一个类的实例变得简单 **程序示例** 我们需要一个通用的方案来解决映射问题。让我们来介绍一个通用的转换器。 ```java public class Converter { private final Function fromDto; private final Function fromEntity; public Converter(final Function fromDto, final Function fromEntity) { this.fromDto = fromDto; this.fromEntity = fromEntity; } public final U convertFromDto(final T dto) { return fromDto.apply(dto); } public final T convertFromEntity(final U entity) { return fromEntity.apply(entity); } public final List createFromDtos(final Collection dtos) { return dtos.stream().map(this::convertFromDto).collect(Collectors.toList()); } public final List createFromEntities(final Collection entities) { return entities.stream().map(this::convertFromEntity).collect(Collectors.toList()); } } ``` 专属的转换器像下面一样从基类继承。 ```java public class UserConverter extends Converter { public UserConverter() { super(UserConverter::convertToEntity, UserConverter::convertToDto); } private static UserDto convertToDto(User user) { return new UserDto(user.getFirstName(), user.getLastName(), user.isActive(), user.getUserId()); } private static User convertToEntity(UserDto dto) { return new User(dto.getFirstName(), dto.getLastName(), dto.isActive(), dto.getEmail()); } } ``` 现在,在User和UserDto之间的映射变得轻而易举。 ```java var userConverter = new UserConverter(); var dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com"); var user = userConverter.convertFromDto(dtoUser); ``` ## 类图 ![alt text](../../../converter/etc/converter.png "Converter Pattern") ## 适用性 在下面这些情况下使用转换器模式: * 如果你的类型在逻辑上相互对应,并需要在它们之间转换实体 * 当你想根据上下文提供不同的类型转换方式时 * 每当你引入DTO(数据传输对象)时你可能都需要将其转换为 DO ## 鸣谢 * [Converter](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)