在Java中,单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。以下是几种常见的实现单例模式的方法:
这种方法是线程安全的,因为实例在类加载时就创建好了。
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
// 私有构造函数防止外部实例化
}
public static Singleton getInstance() {
return INSTANCE;
}
}
这种方法是线程不安全的,因为实例在第一次调用getInstance()
方法时才创建。
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数防止外部实例化
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种方法是线程安全的,通过双重检查锁定(Double-Checked Locking)来确保实例的唯一性和线程安全。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
// 私有构造函数防止外部实例化
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
枚举是实现单例模式的一种简洁且线程安全的方式。
public enum Singleton {
INSTANCE;
public void doSomething() {
// 业务逻辑
}
}
这种方法是线程安全的,并且实现了延迟加载。
public class Singleton {
private Singleton() {
// 私有构造函数防止外部实例化
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
虽然不推荐,但可以通过反射和序列化来破坏单例模式。为了防止这种情况,可以在单例类中添加相应的检查和处理逻辑。
import java.io.Serializable;
public class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
// 私有构造函数防止外部实例化
}
public static Singleton getInstance() {
return INSTANCE;
}
protected Object readResolve() {
return getInstance();
}
}
选择哪种实现方式取决于具体的需求和场景。如果需要线程安全且延迟加载,可以使用静态内部类或枚举;如果对性能有较高要求,可以使用饿汉式或双重检查锁定。