目录
在 Java 中,常见的单例模式有以下几种写法:
1.饿汉式单例模式:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
这种写法的特点是在类加载时就创建了单例对象,因此又被称为饿汉式单例模式。由于单例对象在类加载时就已经创建好了,所以它是线程安全的。但是,这种写法的缺点是如果单例类的构造函数中存在耗时的操作,可能会导致类加载慢,在一些场景下不太合适。
2.懒汉式单例模式:
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种写法的特点是在第一次调用 getInstance() 方法时才创建单例对象,因此又被称为懒汉式单例模式。由于单例对象在第一次调用 getInstance() 方法时才会被创建,所以在多线程环境下需要使用 synchronized 关键字来保证线程安全。但是,这种写法的效率较低,因为每次调用 getInstance() 方法都需要加锁,耗费较多的时间
3、双重校验锁式单例模式:
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;
}
}
这种写法的特点是在第一次调用 getInstance() 方法时才创建单例对象,且使用了双重校验锁的机制来保证线程安全。这种写法的优点是在多线程环境下可以保证单例对象的唯一性,同时又不会影响程序的效率,因为在单例对象已经被创建之后,后续的调用 getInstance() 方法都不会进行加锁操作。
4、静态内部类式单例模式:
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
这种写法的特点是使用了静态内部类的机制来保证单例对象的唯一性。在这种写法中,我们定义了一个静态内部类 SingletonHolder,在该类中定义了一个静态变量 INSTANCE,该变量在类加载时就会被初始化为单例对象。在外部类的 getInstance() 方法中,我们只需要返回 SingletonHolder.INSTANCE 即可。由于静态内部类的特性,单例对象只会在第一次调用 getInstance() 方法时被创建,因此这种写法又被称为延迟加载单例模式。这种写法的优点是在多线程环境下可以保证单例对象的唯一性,同时又不会影响程序的效率。
5、枚举式单例模式:
public enum Singleton {
INSTANCE;
public void doSomething() {
// do something
}
}
这种写法的特点是使用了枚举类型来实现单例模式。枚举类型在 Java 中是一种特殊的类,它的对象数量是有限的,而且在编译期间就已经确定。在这种写法中,我们只需要定义一个枚举常量 INSTANCE 即可,在调用 Singleton.INSTANCE 时就会返回单例对象。这种写法的优点是简单易写,同时在多线程环境下也是线程安全的。
6、容器式单例模式:
public class Singleton {
private static Map<String, Object> singletonMap = new HashMap<>();
private Singleton() {}
public static void registerService(String key, Object instance) {
if (!singletonMap.containsKey(key)) {
singletonMap.put(key, instance);
}
}
public static Object getService(String key) {
return singletonMap.get(key);
}
}
这种写法的特点是将单例对象存储在一个容器(如 Map)中,通过 registerService 和 getService 方法来管理单例对象。这种写法的优点是可以管理多个单例对象,同时在多线程环境下也是线程安全的。
7、工厂方法式单例模式:
public class SingletonFactory {
private static Singleton instance;
static {
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
这种写法的特点是将单例对象的创建封装在工厂方法中,通过调用工厂方法来获取单例对象。在这种写法中,我们可以定义多个工厂方法来创建不同的单例对象。这种写法的优点是可以灵活地管理多个单例对象,同时在多线程环境下也是线程安全的。
这些是 Java单例模式的常见写法,但这并不是绝对的,也可能有其他的写法。单例模式的关键在于保证在整个程序运行期间只有一个单例对象存在,因此在设计单例模式时要注意保证线程安全,并考虑程序的效率和可扩展性。