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);