在 Java 中扩展单例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16270353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extending a singleton in Java
提问by Arhowk
What I'd like to do is just make a class that when you extend it, you automatically get the getInstance class. The problem is, when i extend it, I can't reference the child class. The only way I could see to do it is by typecasting ((ClassName)class.getInstance()) but its not very user-friendly. Any suggestions?
我想做的只是创建一个类,当您扩展它时,您会自动获得 getInstance 类。问题是,当我扩展它时,我无法引用子类。我能看到的唯一方法是通过类型转换 ((ClassName)class.getInstance()) 但它不是很用户友好。有什么建议?
回答by Evgeniy Dorofeev
You cannot extend a proper Singleton since it's supposed to have a private constructor:
你不能扩展一个合适的单例,因为它应该有一个私有构造函数:
Effective Java Item 2: Enforce the singleton property with a private constructor
Effective Java Item 2:使用私有构造函数强制实现单例属性
回答by pickypg
The only way to override a singleton is to have a singleton that expects to be overridden. The simplest way to do this is to provide Singleton that implements an interface
(or is otherwise fully abstract
itself) that internally instantiates an injected singleton upon the first use of getInstance()
.
覆盖单例的唯一方法是拥有一个期望被覆盖的单例。做到这一点的最简单方法是提供单例,它实现了一个interface
(或完全abstract
本身),在第一次使用时在内部实例化注入的单例getInstance()
。
public interface SingletonMethods // use a better name
{
String getName();
void doSomething(Object something);
}
public class Singleton // use a better name
{
private Singleton() { /* hidden constructor */ }
public static SingletonMethods getInstance()
{
return SingletonContainer.INSTANCE;
}
/**
* Thread safe container for instantiating a singleton without locking.
*/
private static class SingletonContainer
{
public static final SingletonMethods INSTANCE;
static
{
SingletonMethods singleton = null;
// SPI load the type
Iterator<SingletonMethods> loader =
ServiceLoader.load(SingletonMethods.class).iterator();
// alternatively, you could add priority to the interface, or
// load a builder than instantiates the singleton based on
// priority (if it's a heavy object)
// then, you could loop through a bunch of SPI provided types
// and find the "highest" priority one
if (loader.hasNext())
{
singleton = loader.next();
}
else
{
// the standard singleton to use if not overridden
singleton = new DefaultSingletonMethods();
}
// remember singleton
INSTANCE = singleton;
}
}
}