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;
}}
答案 0 :(得分:1)
但是我使用泛型返回精确的实例时遇到问题 用户想要的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);
答案 1 :(得分:0)
如果您需要获得显式返回类型,则可以使用generic factory method,如下所示:
class Base {}
class A extends Base {}
class B extends Base {}
class InitializationFailedException extends RuntimeException {
public InitializationFailedException(Throwable cause) {
super(cause);
}
}
class Factory {
private static Logger log = LoggerFactory.getLogger(Factory.class);
private static final ConcurrentHashMap<Class<? extends Base>, Base> instances = new ConcurrentHashMap<>();
public static <T extends Base> T getInstance(Class<T> tClass) {
if (tClass == null) {
throw new NullPointerException();
}
return (T) instances.computeIfAbsent(tClass, (tClass1) -> {
try {
return tClass1.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
log.error("Unable to create singleton value for " + tClass1.getCanonicalName(), e);
throw new InitializationFailedException(e);
}
});
}
}
使用这种方法,您可以获得创建的子类型引用:
A aInstance = Factory.getInstance(A.class);
B bInstance = Factory.getInstance(B.class);
您的问题方法签名可能如下所示:
public static <T extends DBManager> T getInstance(Class<T> dbManagerClass);
实例Map应如下所示:
private static final Map<Class<? extends DBManager>, DBManager> instances = new HashMap<>();