java - 使用泛型在 Java 中实现工厂模式

标签 java generics design-patterns factory

我需要 Java 泛型方面的帮助。 我的模型是:我有一些扩展 Dto(数据传输对象)的类和一些扩展实体(我的对象模型到 DB)的类。 我有

interface Mapper<D extends Dto, E extends Entity>{
//Convert a Entity to Dto.
D toDto(E entity);

我有一些实现此接口(interface)的类(即 PersonMapper、BookMapper 等等)。

@Component    
public class PersonMapper implements Mapper<PersonDto, PersonEntity> {
    //implementation
    }

@Component    
public class BookMapper implements Mapper<BookDto, BookEntity> {
    //implementation
    }

我想做的是使用工厂模式以便在运行时选择我的映射器,这取决于我传入输入的字符串。

@Autowired
private PersonMapper personMapper;
@Autowired
private BookMapper bookMapper;    

public <D extends Dto, E extends Entity> Mapper<D, E> selectMapper(String entity){
      if ("Person".equalsIgnoreCase(entity))
         return personMapper;
      if("Book".equalsIgnoreCase(entity))
        return bookMapper;
      ...
    }

在这种情况下,我有以下编译错误:

Type mismatch: cannot convert from PersonMapper to Mapper<D,E>

我的解决方案:

1)

return (Mapper<D, E>) personMapper;

但我有一个警告:

Type Safety: `Unchecked class from personMapper to Mapper<D,H>`

2)

使用 WildCard 和 castingb

public Mapper<Dto, Entity> selectMapper(String entity){
          Mapper<? extends Dto, ? extends Entity> toReturn = null;
          if ("Person".equalsIgnoreCase(entity))
             toReturn = personMapper;
          else if("Book".equalsIgnoreCase(entity))
            toReturn = bookMapper;
          ...
          return (Mapper<Dto, Entity>) toReturn;
        }

但在这种情况下我还有一次警告:

Type safety: Unchecked cast from Mapper<capture#29-of ? extends Dto,capture#30-of ? extends Entity> to Mapper<Dto,Entity>

它有效,但它似乎不是一个干净的解决方案

3) 使用通配符作为返回类型:

public Mapper<? extends Dto, ? extends HistoryEntity> selectMapper(String entity)

但是你知道,根本不推荐使用通配符作为返回类型,这对我也没有帮助,因为我想使用这个映射器并调用 mapper.toDto 确保返回类型是扩展 Dto 的东西。

============================================ ==========================

我不解释为什么要写这样的类构造器

public Service<D extends Dto, E extends Entity>{  
   public Service(Mapper<D,E> mapper){ 
      this.mapper = mapper; 
   } 
} 

然后我注入(inject)(例如)bookMapper 它起作用了。

相反,如果 Mapper 是返回类型,我将无法执行此类操作。

============================================ ==========================

我请求你的帮助是:

我如何使用干净的代码原则(避免编译警告、sonarlint 问题等)编写解决方案以实现这种逻辑?

非常感谢,如果您花一点时间帮助我解决我的问题,我将不胜感激。

最佳答案

那些关于调用者而不是你的代码的变量(D 和 E)。 D和E是由调用者决定的,所以绝对没有办法保证PersonDTO。适合。

制作Mapper<? extends DTO, ? extends Entity> (并且没有变量),并且鉴于这些已经是下限,只是 Mapper<?, ?> - 那行得通,你可以写你的 return没有任何强制转换且没有编译器错误或警告的语句。

当然,这意味着调用者有一个几乎无用的类型。

泛型完全基于“编译时/写入时”。 JVM ( java.exe ) 不知道泛型是什么,事实上它们中的大多数都无法在编译过程中存活下来。 泛型的唯一目的是让编译器标记不正确的代码并避免某些类型转换,仅此而已

将该字符串转换为 Mapper 的本质完全是运行时的。

因此,如果 Mapper<?, ?>还不够,你想要的是不可能的。你需要编写编译/写入时可检查的东西,所以当你使用字符串时,这是不可能的。例如,一个方法 getPersonMapper()当然可以返回 Mapper<PersonDTO, PersonEntity> ,没问题。

更笼统地说(嘿),听起来您在这里糟糕地重新发明了各种轮子。查看 JDBI、JOOQ 和 Hibernate 的教程,了解通常如何编写与数据库交互的 Java 代码。

关于java - 使用泛型在 Java 中实现工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70637259/

相关文章:

java - 返回函数 String 中的整数

java - 转换为 char 是否总是被认为是缩小的?

java - 在 5 张牌游戏中找到 4 张相同的牌

c# - 无法使用动态参数和泛型调用扩展方法

java - 在运行时创建具有反射和泛型的类的数组

java - 参数化类的原始使用

java - 抽象类扩展具体类

swift - 调用与我的数据库交互的方法的最佳位置在哪里?

java - 如何在 Java 中创建 XML 属性文件?

java - 函数式编程 : How to handle exceptions in Functional Programming or what is its equivalent