我已经尝试过几次了解Singleton是什么.也许我只是太过视觉化......所以任何人都可以用一个简单的比喻来分解它.
类似帖子:
我在网上读到的关于Singleton设计模式的许多文章都提到该类应该覆盖'clone()'方法,并在其中抛出'CloneNotSupported'异常.这真的有必要吗?
默认情况下,clone()方法是受保护的,因此没有类(同一个包中的类除外)能够在该Singleton实例上调用它.另外,如果此Singleton没有实现Cloneable,那么即使调用此方法,它也会产生运行时异常.另外,构造函数是私有的,我们将无法对其进行子类化,从而允许进行克隆.那么我还应该为我的Singleton类实现这个建议吗?
编辑:只是澄清:我不是在寻找实现Singleton的最佳方法.我只是询问上面提到的建议的有效性,以及"正常"的Singleton模式(而不是基于Enum的Singleton).
这是一个非常广泛的枚举单例代码:
public enum enumClazz{
INSTANCE
enumClazz(){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
和一堆地方说这是一个懒惰的初始化.但在阅读" Java虚拟机内部"第7章- 类型的生命周期后,我感到困惑:
Java虚拟机规范为类和接口加载和链接的时序提供了实现的灵活性,但严格定义了初始化的时间.所有实现必须在其第一次活动使用时初始化每个类或接口.以下六种情况符合有效用途:
- 创建一个类的新实例(在字节码中,执行新指令.或者,通过隐式创建,反射,克隆或反序列化.)
- 调用由类声明的静态方法(在字节码中,执行invokestatic指令)
- 使用或赋值由类或接口声明的静态字段,除了最终的静态字段并由编译时常量表达式初始化(在字节码中,执行getstatic或putstatic指令)
- 在Java API中调用某些反射方法,例如Class类中的方法或java.lang.reflect包中的类
- 初始化类的子类(类的初始化需要事先初始化其超类.)
- 在Java虚拟机启动时将类指定为初始类(使用main()<方法)
粗体风格的第三点澄清了如果字段是static final,则字段的初始化发生在编译时.同样,INSTANCEin enumClazz隐含地等于public static final并符合第三点.
如果我的理解错了,有人可以纠正我吗?
今天在我的采访中,一位采访者让我写了一个Singleton课程.我给出了答案
public class Singleton {
private static Singleton ref;
private Singleton() {
}
public static Singleton getInstance() {
if (ref == null) {
ref = new Singleton();
}
return ref;
}
}
Run Code Online (Sandbox Code Playgroud)
突然他告诉我这是写作课的老方法.任何人都可以帮助我,为什么他这样说.
我有一个像这样的单身人士.
public class BookingFactory {
private final static BookingFactory instance;
static {
instance = new BookingFactory();
}
public static BookingFactory getInstance() {
return instance;
}
private BookingFactory() {
System.out.println("Object is created.");
}
}
public class Test {
BookingFactory instance = BookingFactory.getInstance();
instance = BookingFactory.getInstance();
Class<?> clazz = Class.forName("com.test.BookingFactory");
Constructor pvtConstructor = clazz.getDeclaredConstructors()[0];
// Set its access control
pvtConstructor.setAccessible(true);
// Invoke Private Constructor
BookingFactory notSingleton = (BookingFactory) pvtConstructor.newInstance(null);
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我看到了多条打印输出消息.有没有办法阻止这个单例从这个反射中被多次实例化?
谢谢.
在多线程环境中使用Singleton类的首选方法是什么?
假设我有3个线程,并且所有线程都试图同时访问getInstance()singleton类的方法 -
synchronized getInstance()方法或使用synchronized块是好的做法getInstance().请告知是否还有其他方法.
我正在开发一个设计模式,我想确保这里只是Java虚拟机中一个类的一个实例,通过一个点来汇集对某些资源的所有请求,但我不知道它是否可行.
我只能想到一种方法来计算类的实例并在创建第一个实例后销毁所有实例.
这是一种正确的方法吗?如果没有,还有其他方法吗?
我最近接受了一次采访,他向我询问了关于它们如何实现的Singleton Design Patterns,并告诉他使用静态变量和静态方法我们可以实现Singleton Design Patterns.
他似乎对答案感到满意,但我想知道
关于Singleton的任何意见都会受到高度赞赏,在处理Singletons时要记住哪些主要内容?
谢谢.
如果我必须在使用该对象之前初始化它,那么初始化基于java enum的单例的正确方法是什么.
我已经开始编写代码,但我不确定我是否做得对.你能帮我实现这个单身对我来说正确吗?
public enum BitCheck {
INSTANCE;
private static HashMap<String, String> props = null;
public synchronized void initialize(HashMap<String, String> properties) {
if(props == null) {
props = properties;
}
}
public boolean isAenabled(){
return "Y".equalsIgnoreCase(props.get("A_ENABLED"));
}
public boolean isBenabled(){
return "Y".equalsIgnoreCase(props.get("B_ENABLED"));
}
}
Run Code Online (Sandbox Code Playgroud) 我读过Effective Java,并指出Singleton最好使用Enum实现.
这种方法在功能上等同于公共字段方法,除了它更简洁,免费提供序列化机制,并提供防止多实例化的铁定保证,即使面对复杂的序列化或反射攻击.虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单例的最佳方法.
尽管如此,这似乎是实现快速序列化和真正的单一实例的权衡,但是你放弃了经典单例的更友好的oop方法.枚举不能被继承,只能扩展一个接口,如果你想提供一个骨架类,你需要创建一个辅助类.
那么,除了上述原因之外,为什么我们应该接受Enum作为Singleton的最佳实现呢?