構建型設計模式-Converter

模式意圖

提供一種通用的方法來實現兩種數據類型之間的相互轉換,從而最大化地減少樣板代碼的編寫。

現實案例

在日常Java開發過程中,我們經常需要根據各種需求做類型轉換,如:

  • 為執行業務處理,經常需要將VO轉換成DTO
  • 為存儲業務數據,經常需要將DTO轉換為PO
  • 為展示相關數據,經常需要將PO轉換為VO
  • 為調用服務提供方接口,經常需要將自己的對象轉換成服務提供方提供的請求對象

解決方案

為解決不同類型之間的轉換問題,我們提供如下兩個類:

  • BDConverter:泛型雙向轉換器,用於處理兩種類型之間需要相互轉換的場景。
  • UDConverter:泛型單向轉換器,用於處理單向轉換場景。

類圖如下:


構建型設計模式-Converter

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  源類型
* @param  目標類型
*/
public class BDConverter {
private final Function forwardFunction;
private final Function reverseFunction;
/**
 ** 構造器
 *  @param forwardFunction 將S轉換為T的正向函數
 * @param reverseFunction 將T轉換為S的逆向函數
 */
public BDConverter(final Function forwardFunction, final Function reverseFunction) {
 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 List forwardConvertWithList(final Collection ss) {
 return ss.stream().map(this::forwardConvertWithOne).collect(Collectors.toList());
}

public final List reverseConvertWithList(final Collection tt) {
 return tt.stream().map(this::reverseConvertWithOne).collect(Collectors.toList());
}
}
/<code>

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  原始類型
* @param  目標類型

*/
public class UDConverter {
private final Function convertFunction;
public UDConverter(Function convertFunction) {
 this.convertFunction = convertFunction;
}
public final T convertFromOne(final S s) {
 return convertFunction.apply(s);
}
 
/**
 **將原始集合轉換為目標列表
 * @param  ss  原始集合

 * @return  目標列表
 */
public final List convertFromCollection(final Collection ss) {
 return ss.stream().map(this::convertFromOne).collect(Collectors.toList());
}
}
/<code>

模式優勢

  • 將類型轉換邏輯從業務代碼中剝離,使類的職責更清晰(單一職責原則)。
  • 複用類型轉換邏輯,同時也方便在一個地方控制類型之間的轉換邏輯。



編程示例

下面我們編寫一個StringSerializer來實現字符串的序列化與反序列化功能,類圖如下:


構建型設計模式-Converter


下面是轉換器實現:

<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實現類不完整截圖:


構建型設計模式-Converter


通過上面的截圖,很容易看出轉換器的實際功能,調用時一目瞭然。


分享到:


相關文章: