单例模式

单例模式的概念

一个类在一定的作用域范围内只允许创建一个对象(或实例),那这个类就是一个单例类,这个设计模式就叫单例模式(Singleton Design Pattern)。根据作用域范围的不同,单例模式的实现思路可能会有不同。

单例模式的使用原因

优雅地处理资源访问冲突

比如一个程序里只有一个日志文件,如果这个日志文件对象在该进程内不是单例的,那么当程序里还有其他线程也要获取这个对象并有写入操作,就得进行互斥访问,编码就会变得较为复杂。

业务逻辑上该类就是只允许创建一个对象

经常业务逻辑上有的类就只允许创建一个对象。

如何设计单例

单例模式的设计思路很多,实现一个单例模式无非要考虑以下几点要求:

  • 隐藏构造方法,不可随意创建对象;
  • 考虑多线程下单例对象的获取是否存在安全问题,以免破坏单例约束;
  • 可能有时候该类的占用资源较大,所有要考虑是否可以延迟加载;
  • 获取单例对象的性能好不好;

以下是常见的集中单例设计方式:

饿汉式

public class DemoSingleton {

	private static final DemoSingleton instance = new DemoSingleton();
	// 隐藏构造方法
	private DemoSingleton() {};
	// 提供获取单例对象的方法
	public static DemoSingleton getInstance() {
		return instance;
	}
	// 业务逻辑
}

饿汉式的优点:

  • 单例对象在类加载时就已经创建并初始化,避免了多线程下单例对象创建时的安全问题;
  • 实现方式简单

饿汉式的缺点:

  • 因为单例对象在类加载时完成创建和初始化,没有延迟加载的效果;

懒汉式

public class DemoSingleton {
	private static final DemoSingleton instance;
	// 隐藏构造方法
	private DemoSingleton() {}
	// 提供获取单例对象的方法
	// 通过使获取单例对象的并发度为1,从而保证多线程下单例对象的获取是安全的
	public static synchronized DemoSingleton getInstance() {
		if (null == instance) {
			instance = new DemoSingelton();
		}
		return instance;
	}
	// 业务逻辑
}

懒汉式的优点:

  • 可以实现单例对象延迟加载;
  • 实现上简单粗暴,符合单例模式的直观思维;

懒汉式的缺点:

  • 获取单例对象的并发度过低,高并发下性能差;

懒汉式优化—双重检测

public DemoSingleton {
	private static volatile DemoSingleton instance;
	// 隐藏构造方法
	private DemoSingleton() {};
	// 提供公开的获取单例对象的方法
	public static DemoSingleton getInstance() {
		if (null == instance) {
			synchronized(DemoSingleton.class) {	// 进程级别的锁,如果换成分布式锁就能实现分布式下的单例
				if (null == instance) {
					instance = new DemoSingleton();
				}
			}
		}
		return instance;
	}
	// 业务逻辑
}

双重检测的优点:

  • 相比懒汉式提高了性能,也具备延迟加载特性
  • 设计模型比较完备,容易类比(比如说很容易类比出分布式下的单例模式设计方法)

双重检测的缺点:

  • 实现逻辑上比较繁琐,技术细节会比较多

静态内部类

public class DemoSingleton {
	// 隐藏构造方法
	private DemoSingleton() {}
	// 静态内部类
	private static class SingletonHolder {
		private static final DemoSingleton instance = new DemoSingleton();
	}
	// 对外获取单例对象的方法
	public static DemoSingleton getInstance() {
		return SingletonHolder.instance;
	}
	// 业务逻辑
}

优点:

  • 简单高效,又达到了延迟加载的目的

缺点:

  • 依赖了java的语言特性

枚举

public enum DemoSingleton {
	INSTANCE;
	// 业务逻辑
}

优点:

  • 代码实现上非常简洁;
  • 最为安全(语言特性上保证了序列化和反序列化都不会破坏单例性)

缺点:

  • 依赖java的语言特性

参考

【1】极客时间—设计模式之美
【2】 《java设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值