java - 使用泛型和反射的单例工厂

标签 java generics reflection singleton factory

OrderDBManager、UserDBManager、ProductDBManager 扩展了 DBManager。 我正在尝试创建一个单例 DBManager Factory 获取不同 DBManager 类型类的实例。

但是我在使用泛型返回用户想要的确切 DBManager 类型类的实例时遇到问题。目前它仅适用于 DBManager 本身。 我将感谢您的帮助!

public class DBManagerFactory {

     private static final Map<String, DBManager> instances = new HashMap<>();

     private static final String DB_MANAGER_PACKAGE_NAME = "ua.Test.db.";

     public static DBManager getInstance(Class<? extends DBManager> dbManagerClass) {
            String dbManagerClassName = dbManagerClass.getSimpleName();
            DBManager dbManager = instances.get(dbManagerClassName);

            if(dbManager == null){
                Class clazz = Class.forName(DB_MANAGER_PACKAGE_NAME + dbManagerClassName);
                dbManager = (DBManager)clazz.newInstance();
                instances.put(dbManagerClassName, dbManager);    
            }
            return dbManager;                                             
     }}                                                                

最佳答案

But I have a problem using generics to return an instance of exact DBManager type class user wants.

要在方法中返回特定类,您应该指定一个作用域方法参数化类型,该类型允许类的客户端指定该方法应返回哪种类型。

您可以这样声明该方法:

public static <T extends DBManager> T getInstance(Class<T> dbManagerClass)  {

为了避免不安全的转换,您可以转换 DBManagerMap<String, DBManager> 检索实例到 T extends DBManager使用 Class#cast(Object ) 键入在强制转换 DBManager 之前为您执行类型检查的方法实例:

T dbManager = dbManagerClass.cast(instances.get(dbManagerClassName));

最后,获取类的方法:

Class clazz = Class.forName(DB_MANAGER_PACKAGE_NAME + dbManagerClassName);

不是必需的,因为您已经将类作为方法的参数。
直接使用即可。

以下是实现此解决方案的示例代码:

public class DBManagerFactory {

    private static final Map<String, DBManager> instances = new HashMap<>();

    public static <T extends DBManager> T getInstance(Class<T> dbManagerClass)  {

      final String dbManagerClassName = dbManagerClass.getSimpleName();

      T dbManager = dbManagerClass.cast(instances.get(dbManagerClassName));

      if (dbManager == null) {
        try {
          dbManager =  dbManagerClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
          e.printStackTrace(); // or better log it
          throw new RuntimeException("faillure during reflection instantiation for class " + dbManagerClass.getName(), e);
        }
        instances.put(dbManagerClassName, dbManager);
      }

      return dbManager;
    }   

}

通过这些修改,客户端类可以通过以下方式调用该方法:

DBManager instance = DBManagerFactory.getInstance(DBManager.class);
DBManagerChild child = DBManagerFactory.getInstance(DBManagerChild.class);

关于java - 使用泛型和反射的单例工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44354699/

相关文章:

java - 如何限制 spring security 可保护的类?

java - 如何对大量整数进行排序?

java - 如果我想使用泛型参数调用泛型方法,该怎么办?

java - 如何在java中读取对象并将其写入文本文件?

c# - 更快地替代 Dictionary<TKey, TValue>

java - 通用工厂模式-如何处理返回类型

java - 文本 "<? >"有什么特殊含义吗?

c# - 循环中的高效反射

java - 将给定的类(比方说,java.lang.Object)转换为字节数组。是否可以?

asp.net - 使用反射将连接字符串添加到 ConfigurationManager.ConnectionString 的危险