2017-03-10 20:08:58 +01:00
|
|
|
---
|
|
|
|
layout: pattern
|
|
|
|
title: Converter
|
|
|
|
folder: converter
|
|
|
|
permalink: /patterns/converter/
|
2019-12-13 21:09:28 +02:00
|
|
|
categories: Creational
|
2021-05-19 10:49:05 -06:00
|
|
|
language: en
|
2017-03-10 20:08:58 +01:00
|
|
|
tags:
|
2019-12-13 21:09:28 +02:00
|
|
|
- Decoupling
|
2017-03-10 20:08:58 +01:00
|
|
|
---
|
|
|
|
|
|
|
|
## Intent
|
2020-08-29 16:23:28 +03:00
|
|
|
|
|
|
|
The purpose of the Converter pattern is to provide a generic, common way of bidirectional
|
2017-03-11 12:24:48 +01:00
|
|
|
conversion between corresponding types, allowing a clean implementation in which the types do not
|
2020-08-29 16:23:28 +03:00
|
|
|
need to be aware of each other. Moreover, the Converter pattern introduces bidirectional collection
|
2017-03-11 12:24:48 +01:00
|
|
|
mapping, reducing a boilerplate code to minimum.
|
2017-03-10 20:08:58 +01:00
|
|
|
|
2019-11-16 21:06:05 +02:00
|
|
|
## Explanation
|
|
|
|
|
|
|
|
Real world example
|
|
|
|
|
2020-08-29 16:23:28 +03:00
|
|
|
> In real world applications it is often the case that database layer consists of entities that need
|
|
|
|
> to be mapped into DTOs for use on the business logic layer. Similar mapping is done for
|
|
|
|
> potentially huge amount of classes and we need a generic way to achieve this.
|
2019-11-16 21:06:05 +02:00
|
|
|
|
|
|
|
In plain words
|
|
|
|
|
|
|
|
> Converter pattern makes it easy to map instances of one class into instances of another class.
|
|
|
|
|
|
|
|
**Programmatic Example**
|
|
|
|
|
2020-08-29 16:23:28 +03:00
|
|
|
We need a generic solution for the mapping problem. To achieve this, let's introduce a generic
|
|
|
|
converter.
|
2019-11-16 21:06:05 +02:00
|
|
|
|
|
|
|
```java
|
|
|
|
public class Converter<T, U> {
|
|
|
|
|
|
|
|
private final Function<T, U> fromDto;
|
|
|
|
private final Function<U, T> fromEntity;
|
|
|
|
|
|
|
|
public Converter(final Function<T, U> fromDto, final Function<U, T> 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<U> createFromDtos(final Collection<T> dtos) {
|
|
|
|
return dtos.stream().map(this::convertFromDto).collect(Collectors.toList());
|
|
|
|
}
|
|
|
|
|
|
|
|
public final List<T> createFromEntities(final Collection<U> entities) {
|
|
|
|
return entities.stream().map(this::convertFromEntity).collect(Collectors.toList());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The specialized converters inherit from this base class as follows.
|
|
|
|
|
|
|
|
```java
|
|
|
|
public class UserConverter extends Converter<UserDto, User> {
|
|
|
|
|
|
|
|
public UserConverter() {
|
2019-12-15 00:02:45 +05:30
|
|
|
super(UserConverter::convertToEntity, UserConverter::convertToDto);
|
2019-11-16 21:06:05 +02:00
|
|
|
}
|
2019-12-15 00:02:45 +05:30
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2019-11-16 21:06:05 +02:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-08-29 16:23:28 +03:00
|
|
|
Now mapping between `User` and `UserDto` becomes trivial.
|
2019-11-16 21:06:05 +02:00
|
|
|
|
|
|
|
```java
|
2019-12-15 00:02:45 +05:30
|
|
|
var userConverter = new UserConverter();
|
|
|
|
var dtoUser = new UserDto("John", "Doe", true, "whatever[at]wherever.com");
|
|
|
|
var user = userConverter.convertFromDto(dtoUser);
|
2019-11-16 21:06:05 +02:00
|
|
|
```
|
|
|
|
|
2019-12-07 20:01:13 +02:00
|
|
|
## Class diagram
|
2020-08-29 16:23:28 +03:00
|
|
|
|
2019-12-07 20:01:13 +02:00
|
|
|

|
|
|
|
|
2017-03-10 20:08:58 +01:00
|
|
|
## Applicability
|
2020-08-29 16:23:28 +03:00
|
|
|
|
2017-03-11 12:24:48 +01:00
|
|
|
Use the Converter Pattern in the following situations:
|
2017-03-10 20:08:58 +01:00
|
|
|
|
2020-08-29 16:23:28 +03:00
|
|
|
* When you have types that logically correspond with each other and you need to convert entities
|
|
|
|
between them.
|
|
|
|
* When you want to provide different ways of types conversions depending on the context.
|
|
|
|
* Whenever you introduce a DTO (Data transfer object), you will probably need to convert it into the
|
|
|
|
domain equivalence.
|
2017-03-10 20:08:58 +01:00
|
|
|
|
|
|
|
## Credits
|
|
|
|
|
2021-01-30 14:54:14 +02:00
|
|
|
* [Converter Pattern in Java 8](http://www.xsolve.pl/blog/converter-pattern-in-java-8/)
|