当前位置: 首页 > 知识库问答 >
问题:

对象转换器设计模式的泛型实现

弓举
2023-03-14

我试图创建一个通用对象转换器,为我的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);
  }

}

共有1个答案

鲁淇
2023-03-14

解决该问题的一种方法是将作为转换一部分的类型显式存储在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 */ 
    }
}
 类似资料:
  • 问题内容: 我有一堂课 具有通用属性 有更好的方法来执行以下操作吗? 即以不同的形式返回泛型? 精度,我使用Gson作为反序列化器,以获取列表,然后每个Data对象都可以是异构的 。还可以注册适配器以进行浮点和长检测,但不会更快或更漂亮 编辑 :gson无法检索多头: 要么: java.lang.Double无法转换为java.lang.Long 要么 java.lang.NumberFormat

  • 我有一个类<代码>数据 具有泛型属性 有没有更好的方法来做以下事情? 即以不同的形式返回泛型类型? Precision,我使用Gson作为反序列化器,以获得一个列表,每个数据对象可以是异构的< br >也可以注册适配器进行浮点和长整型检测,但它不会更快或更好 编辑:gson无法检索longs: 或者: java.lang.Double不能java.lang.Long 或 java.lang.Num

  • 问题内容: 我需要一个对象池,而不是自己实现,我想我应该找一个现成的且经过测试的Python库。 我发现很多其他人正在寻找,但没有得到很多直接的答案,因此我将其带到了Stack Overflow。 就我而言,我有大量线程(使用模块),这些线程有时需要调用基于SOAP的远程服务器。他们每个人都可以建立自己与服务器的连接,但是设置套接字并完成身份验证过程非常昂贵(这受服务器的限制),因此我想共享一个连

  • 空对象(Null) Intent 使用什么都不做 的空对象来代替 NULL。 一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。 Class Diagram Implementation // java public abstract clas

  • 问题内容: 我需要为我的可定制搜索界面(正在编写的Web应用程序)在Java中实现查询对象模式。 有人知道我可以从哪里获得查询对象模式的示例/教程(马丁·福勒的QoP)吗? 提前致谢 附加 如何将查询模式添加到现有DAO模式? 问题答案: “查询对象模式”中的单词“模式”放错了位置(IMHO)。这不是真正的设计模式。“查询对象”只是解释器模式的另一个示例。遗留的Hibernate Criteria

  • 我正在创建一个由数组支持的泛型类型堆栈。当我尝试创建泛型类型数组时,Java不允许我这样做。有人告诉我,我必须创建一个类型为Object的数组,并将其转换为泛型类型。我已经将对象数组转换为类型,但如何处理Java不断给我的未检查类型错误? 这就是我目前所处的位置。 更新:我正在创建一个对象数组,然后在方法的末尾将返回类型转换为T类型。