单例模式
单例模式
什么是单例模式
单例模式是一种创建型设计模式,它的目的是确保一个类只有一个实例,并提供对该实例的全局访问点。
它通常适用于需要对某个资源(如数据库连接池、日志输出等)进行管理的情况,以避免多个实例竞争资源造成的冲突。
为什么需要单例模式
在实际的应用中,有些情景需要我们仅仅只想获取或使用某个类的一个实例,而不是多个实例。这时候就需要使用单例模式。
单例模式可以避免由于多次实例化而造成的资源浪费。同时也避免了多个实例之间互相调用而导致的冲突。
因此,我们必须要确保某个类始终只有一个实例。参考 JDK 中的 java.lang.Runtime
和 java.awt.Desktop
类。
如何实现单例模式
懒汉式
懒汉式指的是当我们需要使用这个类的实例时,才去创建它。
public class Singleton {
private static Singleton singletonInstance = null;
private Singleton() {}
public static Singleton getInstance() {
if (singletonInstance == null) {
singletonInstance = new Singleton();
}
return singletonInstance;
}
}
饿汉式
饿汉式指的是在类加载时就已经初始化好了实例,可以在后面的调用过程中直接获取实例。
public class Singleton {
private static final Singleton singletonInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return singletonInstance;
}
}
双重检验锁
双重检验锁的核心在于一个 volatile
类型的变量和一个加锁的代码块。
public class Singleton {
private static volatile Singleton singletonInstance = null;
private Singleton() {}
public static Singleton getInstance() {
if (singletonInstance == null) {
synchronized (Singleton.class) {
if (singletonInstance == null) {
singletonInstance = new Singleton();
}
}
}
return singletonInstance;
}
}
静态内部类
静态内部类指的是将单例类放到静态内部类中,只有在第一次调用时,才会去实例化一个单例的 AbstractSingleton。
public class Singleton {
private static class SingletonHolder {
private static final Singleton singletonInstance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.singletonInstance;
}
}
枚举
枚举相当于一种更加简化的静态内部类的版本,在这种情况下,枚举被当作是一种单例的实现方式。
public enum Singleton {
INSTANCE;
public void doSomething() {
// ...
}
}
单例模式的优缺点
优点
- 确保一个类只有一个实例,避免多次实例化造成的资源浪费。
- 提供对唯一实例的全局访问点,方便对该实例的控制。
缺点
- 单例模式一般违反了单一职责原则,因为它同一时间只能做一件事情。
- 单例模式可能导致一些设计问题,如难以测试、容易被其他代码调用等。
- 单例模式可能导致不必要的延迟加载,即在使用时才去实例化一个单例实例,这个过程有时候可能会使应用变慢。
总结
单例模式是一种非常实用的设计模式,在需要对某个资源进行统一管理且不会存在多个实例时可以使用。
我们可以采用懒汉式、饿汉式、双重检验锁、静态内部类、枚举等方式来实现单例模式。
单例模式的优点在于确保了类只有一个实例,并提供对该实例的全局访问点。但是缺点也显而易见,可能违反单一职责原则,也可能出现设计问题以及不必要的延迟加载等。