转换器模式
目的
转换器模式的目的是提供相应类型之间双向转换的通用方法,允许进行干净的实现,而类型之间无需相互了解。
此外,Converter模式引入了双向集合映射,从而将样板代码减少到最少。
解释
【例子】:在真实的应用中经常有这种情况,数据库层包含需要被转换成业务逻辑层DTO来使用的实体。
对于潜在的大量类进行类似的映射,我们需要一种通用的方法来实现这一点。
通俗的说:转换器模式让一个类的实例映射成另一个类的实例变得简单
示例
通用转换器代码如下:
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Converter<T,U> {
private final Function<T,U> fromDto;
private final Function<U,T> fromEntity;
public Converter(Function<T, U> fromDto, Function<U, T> fromEntity) {
this.fromDto = fromDto;
this.fromEntity = fromEntity;
}
/***
* 从DTO转化成Entity
* @param dto
* @return
*/
public final U convertFromDto(T dto) {
return fromDto.apply(dto);
}
/**
* 从Entity转化成DTO
*
*/
public final T convertFromEntity(final U entity) {
return fromEntity.apply(entity);
}
/***
* 从DTOs转化成Entitys
* @param dtos
* @return
*/
public final List<U> createFromDtos(final Collection<T> dtos) {
return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());
}
/***
* 从Entitys转化成DTOs
* @param entities
* @return
*/
public final List<T> createFromEntities(final Collection<U> entities) {
return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());
}
}
专属的转换器像下面一样从基类继承。
public class UserConverter extends Converter<UserDTO, User> {
public UserConverter(Function<UserDTO, User> fromDto, Function<User, UserDTO> fromEntity) {
super(fromDto, fromEntity);
}
public UserConverter() {
super(UserConverter::convertToEntity, UserConverter::convertToDto);
}
private static UserDTO convertToDto(User user) {
return new UserDTO(user.getName(),user.getAge(),user.getUserId(),user.isVip());
}
private static User convertToEntity(UserDTO dto) {
return new User(dto.getName(),dto.getAge(),dto.getUserId(),dto.isVip());
}
}
User类中的代码如下:
public class User implements Serializable{
private String name;
private int age;
private String userId;
private boolean isVip;
public User() {}
public User(String name, int age, String userId, boolean isVip) {
this.name = name;
this.age = age;
this.userId = userId;
this.isVip = isVip;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public boolean isVip() {
return isVip;
}
public void setVip(boolean vip) {
isVip = vip;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", userId='" + userId + '\'' +
", isVip=" + isVip +
'}';
}
}
UserDTO代码如下:
public class UserDTO implements Serializable {
private String name;
private int age;
private String userId;
private boolean isVip;
private String iphone;
public UserDTO() {
}
public UserDTO(String name, int age, String userId, boolean isVip) {
this.name = name;
this.age = age;
this.userId = userId;
this.isVip = isVip;
}
public UserDTO(String name, int age, String userId, boolean isVip, String iphone) {
this.name = name;
this.age = age;
this.userId = userId;
this.isVip = isVip;
this.iphone = iphone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public boolean isVip() {
return isVip;
}
public void setVip(boolean vip) {
isVip = vip;
}
public String getIphone() {
return iphone;
}
public void setIphone(String iphone) {
this.iphone = iphone;
}
@Override
public String toString() {
return "UserDTO{" +
"name='" + name + '\'' +
", age=" + age +
", userId='" + userId + '\'' +
", isVip=" + isVip +
", iphone='" + iphone + '\'' +
'}';
}
}
现在,在User和UserDTO之间的映射变得轻而易举。
public class App {
public static void main(String[] args) {
Converter<UserDTO, User> userConverter = new UserConverter();
UserDTO dtoUser = new UserDTO("zhangsan",11,"95001",true);
User user = userConverter.convertFromDto(dtoUser);
System.out.println("Entity converted from DTO:"+user);
List<User> users = new ArrayList<>();
users.add(new User("李四",11,"95002",true));
users.add(new User("王五",12,"95003",true));
users.add(new User("赵六",13,"95004",false));
users.add(new User("小小",14,"95005",true));
System.out.println("Domain entities:");
users.stream().map(User::toString).forEach(s -> System.out.printf(s));
System.out.println("DTO entities converted from domain:");
List<UserDTO> dtoEntities = userConverter.createFromEntities(users);
dtoEntities.stream().map(UserDTO::toString).forEach(s -> System.out.printf(s));
}
}
适用性
在下面这些情况下使用转换器模式:
如果你的类型在逻辑上相互对应,并需要在它们之间转换实体
当你想根据上下文提供不同的类型转换方式时
每当你引入DTO(数据传输对象)时你可能都需要将其转换为DO