模式意圖
提供一種通用的方法來實現兩種數據類型之間的相互轉換,從而最大化地減少樣板代碼的編寫。
現實案例
在日常Java開發過程中,我們經常需要根據各種需求做類型轉換,如:
- 為執行業務處理,經常需要將VO轉換成DTO
- 為存儲業務數據,經常需要將DTO轉換為PO
- 為展示相關數據,經常需要將PO轉換為VO
- 為調用服務提供方接口,經常需要將自己的對象轉換成服務提供方提供的請求對象
解決方案
為解決不同類型之間的轉換問題,我們提供如下兩個類:
- BDConverter:泛型雙向轉換器,用於處理兩種類型之間需要相互轉換的場景。
- UDConverter:泛型單向轉換器,用於處理單向轉換場景。
類圖如下:
![構建型設計模式-Converter](http://p2.ttnews.xyz/loading.gif)
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來實現字符串的序列化與反序列化功能,類圖如下:
![構建型設計模式-Converter](http://p2.ttnews.xyz/loading.gif)
下面是轉換器實現:
<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源 的文章