我想从类的字符串名称实例化一个类的实例。(使用 Class.forName().newInstance()。)
问题是:我希望该实例是单例。我可以使用单例模式来做到这一点,除了 newInstance 调用类的默认构造函数,并且对于单例,该构造函数必须是“私有的”。
有解决办法吗?我可以想到一种不太优雅的方法来做到这一点(使用哈希图作为查找表..),但更喜欢更好的解决方案..
谢谢,
我想从类的字符串名称实例化一个类的实例。(使用 Class.forName().newInstance()。)
问题是:我希望该实例是单例。我可以使用单例模式来做到这一点,除了 newInstance 调用类的默认构造函数,并且对于单例,该构造函数必须是“私有的”。
有解决办法吗?我可以想到一种不太优雅的方法来做到这一点(使用哈希图作为查找表..),但更喜欢更好的解决方案..
谢谢,
一个经典的单例也有一个静态的 getInstance() 方法——通过反射而不是使用 newInstance() 来调用它。是的,这是更多的工作,但就是这样......
或者你可以使用setAccessible()调用私有构造函数,但是你会破坏单例并下地狱。
第三,您可以完全避免使用 Singleton 并找到更好的解决方案(通常有)。
您可以使用反射来获取对类的静态工厂方法的引用,然后调用它。工厂方法可以强制执行单例模式
Class c = Class.forName("test.MyClass");
Method factoryMethod = c.getDeclaredMethod("getInstance");
Object singleton = factoryMethod.invoke(null, null);
接着
public class MyClass {
private static MyClass instance;
private MyClass() {
// private c'tor
}
public static synchronized MyClass getInstance() {
if (instance == null) {
instance = new MyClass();
}
return instance:
}
}
警告:单例设计模式可能对您的长期健康有害。
您必须知道构造对象的单例类的方法名称。如果它被称为“instance()”,你可以做类似的事情
Class c = Class.forName("MySingleton");
Method m = c.getDeclaredMethod("instance",null);
MySingleton singleton = m.invoke(null,null);
您可以使用枚举并为每个枚举命名一个 HashMap。或者你可以使用一些依赖注入框架来获得一个单一的东西(Guice?)
编辑好的,我也加入了一个代码示例:
package tests;
public class EnumSingleton {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("tests.Singleton1");
Operation instance = Operation.class.cast(c.getEnumConstants()[0]);
System.out.println(instance.getTHEAnswer());
c = Class.forName("tests.Singleton2");
instance = Operation.class.cast(c.getEnumConstants()[0]);
System.out.println(instance.getTHEAnswer());
}
}
interface Operation {
int getTHEAnswer();
}
enum Singleton1 implements Operation {
INSTANCE;
@Override
public int getTHEAnswer() {
return 42;
}
}
enum Singleton2 implements Operation {
INSTANCE;
@Override
public int getTHEAnswer() {
return 84;
}
}
而且它安全无恙。编辑现在有了一些意义。
你可以依赖静态工厂方法的存在吗?它会依赖于某种命名约定方式,但这会起作用。
底线:如果要知道一个类是单例的,那么它必须对该监管负责。因此,它必须符合该模式的某些实现,如果您想要在这些类中进行动态选择,那么您需要能够预测“工厂”方法。