模式意图
提供一种通用的方法来实现两种数据类型之间的相互转换,从而最大化地减少样板代码的编写。
现实案例
在日常Java开发过程中,我们经常需要根据各种需求做类型转换,如:
- 为执行业务处理,经常需要将VO转换成DTO
- 为存储业务数据,经常需要将DTO转换为PO
- 为展示相关数据,经常需要将PO转换为VO
- 为调用服务提供方接口,经常需要将自己的对象转换成服务提供方提供的请求对象
解决方案
为解决不同类型之间的转换问题,我们提供如下两个类:
- BDConverter:泛型双向转换器,用于处理两种类型之间需要相互转换的场景。
- UDConverter:泛型单向转换器,用于处理单向转换场景。
类图如下:
BDConverter类:
<code>import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Description: 泛型双向转换器
* @author hxj
* @date 2020年4月2日
* @param源类型/<code>
* @param目标类型
*/
public class BDConverter{
private final FunctionforwardFunction;
private final FunctionreverseFunction;
/**
** 构造器
* @param forwardFunction 将S转换为T的正向函数
* @param reverseFunction 将T转换为S的逆向函数
*/
public BDConverter(final FunctionforwardFunction, final FunctionreverseFunction) {
this.forwardFunction = forwardFunction;
this.reverseFunction = reverseFunction;
}
/** 将S对象正向转换为T对象
* @param s 源对象
* @return T 目标对象
*/
public final T forwardConvertWithOne(final S s) {
return forwardFunction.apply(s);
}
/**
**将T对象逆向转换为S对象
* @param t 目标对象
* @return S 源对象
*/
public final S reverseConvertWithOne(final T t) {
return reverseFunction.apply(t);
}
public final ListforwardConvertWithList(final Collection ss) {
return ss.stream().map(this::forwardConvertWithOne).collect(Collectors.toList());
}
public final ListreverseConvertWithList(final Collectiontt) {
return tt.stream().map(this::reverseConvertWithOne).collect(Collectors.toList());
}
}
UDConverter类:
<code>import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Description: 泛型单向转换器
* @author hxj
* @date 2020年4月2日
* @param原始类型/<code>
* @param目标类型
*/
public class UDConverter{
private final FunctionconvertFunction;
public UDConverter(FunctionconvertFunction) {
this.convertFunction = convertFunction;
}
public final T convertFromOne(final S s) {
return convertFunction.apply(s);
}
/**
**将原始集合转换为目标列表
* @param ss 原始集合
* @return 目标列表
*/
public final ListconvertFromCollection(final Collection ss) {
return ss.stream().map(this::convertFromOne).collect(Collectors.toList());
}
}
模式优势
- 将类型转换逻辑从业务代码中剥离,使类的职责更清晰(单一职责原则)。
- 复用类型转换逻辑,同时也方便在一个地方控制类型之间的转换逻辑。
编程示例
下面我们编写一个StringSerializer来实现字符串的序列化与反序列化功能,类图如下:
下面是转换器实现:
<code>import com.ywkj.base.converter.BDConverter;
public class StringSerializer extends BDConverter<string> {
public StringSerializer() {
super(StringSerializer::toByte, StringSerializer::toString);
}
private static byte[] toByte(String s) {
return s.getBytes();
}
private static String toString(byte[] s) {
return new String(s);
}
}/<string>/<code>
使用代码:
<code>public static void main(String[] args) {
StringSerializer converter = new StringSerializer();
String str="abcde";
//正向转换,将String转换成byte[]
byte[] byteArr = converter.forwardConvertWithOne(str);
//反向转换,将byte[]转换成String
String result = converter.reverseConvertWithOne(byteArr);
System.err.println(str.equals(result));
//集合形式的类型转换
List<byte> list = converter.forwardConvertWithList(Lists.newArrayList("a","b"));
List<string> resultList= converter.reverseConvertWithList(list);
System.err.println(resultList);
}/<string>/<byte>/<code>
其它资料
spring framework内部也大量使用了Converter设计模式,下面是Converter实现类不完整截图:
通过上面的截图,很容易看出转换器的实际功能,调用时一目了然。
閱讀更多 Java源 的文章