簡體   English   中英

使用泛型實現對象轉換器設計模式

[英]Implementation for object converter design pattern using generics

我正在嘗試為我的dto < - >實體類創建一個通用對象轉換器。 我創建了一個抽象類,其中兩個函數表示兩個轉換,然后在我的具體轉換器類中擴展它。

但我希望有一個通用的轉換服務,我可以在啟動時注冊所有轉換器,然后方便地調用單個方法來處理彼此之間的轉換。

這是我到目前為止所得到的:

轉換器抽象類

public abstract class Converter<D, E> {

  private final Function<D, E> fromFirstToSecond;
  private final Function<E, D> fromSecondToFirst;

  public Converter(final Function<D, E> fromFirstToSecond, final Function<E, D> fromSecondToFirst) {
    this.fromFirstToSecond = fromFirstToSecond;
    this.fromSecondToFirst = fromSecondToFirst;
  }

  public final E convertFromFirstToSecond(final D first) {
    return fromFirstToSecond.apply(first);
  }

  public final D convertFromSecondToFirst(final E second) {
    return fromSecondToFirst.apply(second);
  }

}

轉換器具體類

public class MyConverter extends Converter<MyDTO, MyEntity> {

    public OrderConverter() {
        super(
            MyConverter::fromDTOToEntity,
            MyConverter::fromEntityToDTO
        );
    }

    private static MyEntity fromDTOToEntity(MyDTO dto) {
        return MyEntity.builder()
            .field1(dto.getField1())
            .field2(dto.getField2())
            .build();
    }

    private static MyDTO fromEntityToDTO(MyEntity entity) {
        return MyDTO.builder()
            .field1(entity.getField1())
            .field2(entity.getField2())
            .build();
    }

}

我想實現這樣的目標(這是我需要幫助的地方):

@Configuration
public class ConverterConfiguration {

  @Bean
  public ConverterService converterService() {
    ConverterService converterService = new ConverterService();
    converterService.registerConverter(new MyConverter());
    // Register any other converter...
    return converterService;
  }

}

該服務看起來像這樣:

public class ConverterService {

  private Map<Key, Converter<?, ?>> converters = new ConcurrentReferenceHashMap<>();

  public void registerConverter(Converter<?, ?> converter) {
    this.converterCache.put(key, converter);
  }

  protected <I, O> I mapBetweenTypes(final O from, final Class<I> clazz) {
    // Based on the parameters I should be able to figure out which function to get from the map and then call (convertFromFirstToSecond or convertFromSecondToFirst)
    // return this.converters.get(key).convertFromFirstToSecond(from);
    return this.converters.get(key).convertFromSecondToFirst(from);
  }

}

解決該問題的一種方法是在Converter類中顯式存儲屬於Converter類型。 我要考慮的另一個簡化是將轉換函數直接存儲在映射中,而不是轉換器。 然后你不必弄清楚你需要走哪條路。

第一步,存儲類型,並為轉換函數添加getter:

public abstract class Converter<D, E> {

  private final Function<D, E> fromFirstToSecond;
  private final Function<E, D> fromSecondToFirst;
  private final Class<D> classOfFirst;
  private final Class<E> classOfSecond;

  public Class<D> getClassOfFirst() {
      return classOfFirst;
  }

  public Class<E> getClassOfSecond() {
      return classOfSecond;
  }

  public Converter(Class<D> first, Class<E> second, 
      Function<D, E> fromFirstToSecond, Function<E, D> fromSecondToFirst) {
    this.fromFirstToSecond = fromFirstToSecond;
    this.fromSecondToFirst = fromSecondToFirst;
    classOfFirst = first;
    classOfSecond = second;
  }

  public Function<D, E> getForward() {
      return fromFirstToSecond;
  }

  public Function<E, D> getBackward() {
      return fromSecondToFirst;
  }

然后, ConverterService可以在兩個方向上存儲轉換函數,轉換相當於在兩級映射中查找。

public class ConverterService {

    private Map<Class<?>, Map<Class<?>, Function<?,?>>> converters = createMap();

    public void registerConverter(Converter<?, ?> converter) {
        if( !converters.containsKey(converter.getClassOfFirst())) {
            converters.put(converter.getClassOfFirst(), createInnerMap());
        }
        if( !converters.containsKey(converter.getClassOfSecond())) {
            converters.put(converter.getClassOfSecond(), createInnerMap());
        }
        converters.get(converter.getClassOfFirst()).put(
            converter.getClassOfSecond(), converter.getForward());
        converters.get(converter.getClassOfSecond()).put(
            converter.getClassOfFirst(), converter.getBackward());
    }

    @SuppressWarnings("unchecked") // Also needs input validation
    protected <D,E> E mapBetweenTypes(D from, E to) {
        return ((Function<D,E>) converters.get(
            from.getClass()).get(to.getClass())).apply(from);
    }

    private static Map<Class<?>, Map<Class<?>, Function<?,?>>> createMap() { 
        return /* Whatever impl you need */ 
    }

    private static Map<Class<?>, Function<?,?>> createInnerMap() { 
        return /* Whatever impl you need */ 
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM