一、单例模式的概念
单例模式是一种创建型模式,它保证一个类只能被实例化一次,并提供了一个访问该实例的全局访问点。单例模式可以用来解决资源统一分配的问题,如线程池、全局缓存等。
单例模式的标准实现包含三个要素:1.私有的构造函数,2.静态变量实例,3.公共的访问方法。而实现单例模式的方式有很多,接下来我们将讨论这些实现方式。
二、单例模式的五种实现方式
下面是单例模式的五种实现方式:
饿汉式
public class Singleton {
一个私有的、静态的、final类型的实例对象
private static final Singleton INSTANCE = new Singleton();
私有构造函数
private Singleton() {}
公开访问点
public static Singleton getInstance() {
return INSTANCE;
}
}
饿汉式单例模式在类加载时已经创建了实例对象,因此不存在线程安全问题,但是如果实例对象很大,会导致启动时间变长。
懒汉式
public class Singleton {
私有的实例对象
private static Singleton instance = null;
私有构造函数
private Singleton() {}
公开访问点
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式单例模式在第一次调用公开访问点时才创建实例对象,解决了饿汉式单例模式启动时间长的问题。但是在多线程环境下,存在线程安全问题,需要加锁。
双重检查
public class Singleton {
一个私有的、volatile类型的实例对象
private static volatile Singleton instance = null;
私有构造函数
private Singleton() {}
公开访问点
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
双重检查单例模式在多线程环境下解决了线程安全问题,并且不需要每次都加锁,相对于懒汉式单例模式有更优的性能。
静态内部类
public class Singleton {
私有构造函数
private Singleton() {}
私有静态内部类
private static class SingletonHolder {
一个私有的、静态的、final类型的实例对象
private static final Singleton INSTANCE = new Singleton();
}
公开访问点
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
静态内部类单例模式在外部类被加载的时候并不会被初始化,只有在调用公开访问点时才会初始化内部类,从而创建实例对象。这种方式既避免了饿汉式单例模式的启动时间长的问题,又避免了懒汉式单例模式的线程安全问题。
枚举
public enum Singleton {
INSTANCE;
公开方法
public void doSomething() {}
}
枚举单例模式是饿汉式单例模式的升级版,它天生就是线程安全的,并且可以防止反序列化创建新的实例对象。其优点在于简洁明了,不需要做额外的工作即可实现单例模式。
三、单例模式的几种实现方式
除了上述五种实现方式之外,还有一些单例模式的实现方式:
延迟初始化占位类
public class Singleton {
私有变量
private String data = "this is a lazy initialized singleton";
私有构造函数
private Singleton() {}
私有静态内部类
private static class Holder {
私有静态变量
private static final Singleton INSTANCE = new Singleton();
}
私有静态初始化方法
private static final Singleton getInstance() {
return Holder.INSTANCE;
}
公开访问点
public String getData() {
return data;
}
}
延迟初始化占位模式是一种比较新颖的单例实现方式,它通过声明一个私有的静态内部类,该内部类包含单例的实例对象,并在第一次调用公开访问点时才初始化该实例对象,从而达到懒汉式单例模式的效果,并且不需要加锁保证线程安全。
ThreadLocal
public class Singleton {
一个私有的ThreadLocal类型的实例对象
private static ThreadLocal instance = new ThreadLocal() {{
initialValue = new Singleton();
}};
私有构造函数
private Singleton() {}
公开访问点
public static Singleton getInstance() {
return instance.get();
}
}
ThreadLocal单例模式是一种较为特殊的单例实现方式,它结合了懒汉式单例模式和多线程环境下线程安全的特性,并且在每个线程中都可以有自己独立的实例对象,从而达到可重入的效果。
四、单例模式的6种实现方式
除了上述介绍的五种实现方式之外,还有一种单例模式的实现方式,来看看它的实现:
注册式单例
public class Singleton {
一个私有的静态Map类型的实例对象
private static Map registry = new ConcurrentHashMap();
静态代码块
static {
Singleton instance = new Singleton();
registry.put(instance.getClass().getName(), instance);
}
protected Singleton() {}
公共静态方法,返回指定名称的单例对象
public static Singleton getInstance(String name) {
if (name == null) {
name = Singleton.class.getName();
}
if (registry.get(name) == null) {
registry.put(name, new Singleton());
}
return registry.get(name);
}
}
注册式单例模式将每个实例对象都注册到一个Map容器中,以便在需要时快速获取。该实现方式相对于其他实现方式来说比较复杂,而且需要考虑线程安全问题。
五、7种方式实现单例模式
虽然单例模式的标准实现方式只有三个要素,但是在实际使用的时候,我们还可以按照以下的七种方式来实现单例模式:
枚举
和上面的枚举单例模式一样,这里就不再重复介绍了。
饿汉式
和上面的饿汉式单例模式一样,这里就不再重复介绍了。
懒汉式
和上面的懒汉式单例模式一样,这里就不再重复介绍了。
双重检查
和上面的双重检查单例模式一样,这里就不再重复介绍了。
静态内部类
和上面的静态内部类单例模式一样,这里就不再重复介绍了。
延迟初始化占位类
和上面的延迟初始化占位类单例模式一样,这里就不再重复介绍了。
ThreadLocal
和上面的ThreadLocal单例模式一样,这里就不再重复介绍了。
六、实现单例模式的类具有
实现单例模式的类具有以下特点:
1.只能被实例化一次;
2.提供一个访问该实例的全局访问点;
3.在多线程环境下保证线程安全;
4.防止反序列化时创建新的实例对象。
七、单例模式的实现
以上方式都是通过私有的构造函数、静态变量以及公开访问点来实现单例模式的。
八、单例模式代码实现
下面是一个简单的单例模式实现的示例代码:
public class Singleton {
一个私有的、静态的、final类型的实例对象
private static final Singleton INSTANCE = new Singleton();
私有构造函数
private Singleton() {}
公开访问点
public static Singleton getInstance() {
return INSTANCE;
}
}
九、总结
单例模式是一种重要的设计模式,它可以帮助我们解决资源统一分配的问题,并且提升了程序的可维护性和可测试性。在实际开发中,我们可以选择适合自己的单例模式实现方式,并注意线程安全问题。
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/240810.html
微信扫一扫
支付宝扫一扫