OrderDBManager,UserDBManager,ProductDBManager扩展了DBManager。
我正在尝试创建一个单例DBManager工厂
获取不同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;
     }}

最佳答案

但是我在使用泛型返回确切的实例时遇到问题
  用户想要的DBManager类型类。


要在方法中返回特定的类,应指定一个有范围方法的参数化类型,该类型可让该类的客户端指定该方法应返回的类型。

您可以通过以下方式声明方法:

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


为避免不安全的转换,您可以使用DBManager方法将从Map<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);

10-05 17:51