在C ++中,我知道可以使用模板创建Singleton基类。它在Andrei Alexandrescu的书“Modern C ++ Design”中有所描述。
可以用Java实现这样的事情吗?
答案 0 :(得分:3)
因为Java的泛型没有具体化,所以不可能以相同的方式实现通用的Singleton。因为泛型类型是从编译代码中“擦除”的,所以单例必须在运行时显式初始化。
结果是,Singleton模板在Java中不会提供太多价值。
答案 1 :(得分:3)
我还没有在Java中看到令人满意的解决方案。有许多使用C ++中的模板或.NET中的泛型的例子,但Java的泛型实现对静态成员有一些限制,这使得这很困难。
我见过的最好的选择是使用静态HashMap和工厂类。这使您可以创建一个可以为任何类的多个单身人士服务的工厂。
有关实施,请参阅this post。
答案 2 :(得分:2)
是的,但所有方法都存在缺陷。它们要么昂贵(使用synchronized
)要么无法进行测试(final static
)。
请参阅右侧的链接:
“现有技术”是指使用容器或工厂,根据需要创建单件,并将它们保存在某种缓存中。参见Spring,Guice等。
答案 3 :(得分:1)
1997年,我尝试用JDK 1.0.2做到这一点,并得出结论,不可能制作一个可继承的单例。据我所知,Java没有获得任何允许这样做的新功能。
但是,手动执行此操作并不涉及很多样板代码,每类可能有10行左右。如果你需要建立某种匿名工厂机制,单例可以实现与实例化协议占位符的接口。
答案 4 :(得分:0)
您可以使用静态HashMap(或Hashtable以确保线程安全)存储所有不同模板的实例,如@ reed-copsey所述。 单例类示例:
public class Singleton<T extends Parent> {
private static HashMap<Class, Singleton> instanceMap = new HashMap<Class, Singleton>();
private Singleton() {
}
public static <T> Singleton getInstance(Class<T> tClass) {
if (!instanceMap.containsKey(tClass))
instanceMap.put(tClass, new Singleton());
return instanceMap.get(tClass);
}
}
您可以将此单例用作:
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance(Child1.class);
Singleton instance2 = Singleton.getInstance(Child1.class);
assert instance1 == instance2;
Singleton instance3 = Singleton.getInstance(Child2.class);
assert instance1 != instance3;
}
Singleton类将针对不同的类类型返回不同的实例。