我想从字符串中实例化一个类的一个实例 班级名称。 (使用Class.forName()。newInstance()。)
问题在于:我希望该实例成为单身人士.. 我可以使用单例模式来做到这一点,除了 newInstance调用类的默认构造函数, 并且使用单例,该构造函数必须是“私有的”..
有解决方案吗?我可以想到一种不那么优雅的方式 这样做(使用hashmap作为查找表..),但更喜欢 一个更好的解决方案..
谢谢,
答案 0 :(得分:8)
经典单例还有一个静态getInstance()方法 - 通过反射调用而不是使用newInstance()。是的,这是更多的工作,但它就是这样......
或者你可以使用setAccessible()来调用私有构造函数,但是你要打破单身人士并下地狱。
第三,你可以避免单独使用Singleton并找到更好的解决方案(通常有)。
答案 1 :(得分:8)
您可以使用反射来获取对类的静态工厂方法的引用,然后调用它。工厂方法可以强制执行单例模式
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:
}
}
警告:单身人士设计模式可能对您的长期健康不利。
答案 2 :(得分:2)
您必须知道构造对象的单例类的方法名称。 如果它是例如称为“instance()”,您可以执行类似
的操作Class c = Class.forName("MySingleton");
Method m = c.getDeclaredMethod("instance",null);
MySingleton singleton = m.invoke(null,null);
答案 3 :(得分:1)
您可以使用枚举并为每个枚举命名一个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;
}
}
它安然无恙。 修改现在有一些意义。
答案 4 :(得分:0)
您是否可以依赖静态工厂方法的存在?它将依赖于某种方式的命名约定,但这可行。
底线:如果要知道一个类是单身,那么它必须对该监管负责。因此,它必须符合模式的某些实现,如果您想在这些类中进行动态选择,那么您需要能够预测“工厂”方法。