单例模式(Singleton Pattern)-23种常用设计模式快速入门教程
1.单例模式定义
单例模式是一种创建型设计模式,它确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2.单例模式优点
它可以节省资源,提高性能,避免对资源的多重占用,提供一个全局访问点,可以全局访问一个实例。
3.单例模式缺点
当想要生成多个实例时,不能使用单例模式。
4.单例模式示例代码
传统设计模式讲解时使用的示例代码,大都采用与读者日常生活接解的业务系统没有多大关联关系。以致大部分读者无法做到学以致用,学完就忘记。本文采用使用日常生活中随处可见的优惠券业务来编写实现代码:
//定义单例模式的一个单例类
public class CouponManager {
//私有化构造方法,防止外部创建实例
private CouponManager() {}
//私有静态变量,保存实例
private volatile static CouponManager instance;
//提供全局访问点
public static CouponManager getInstance() {
if (instance == null) {
synchronized (CouponManager.class) {
if (instance == null) {
instance = new CouponManager();
}
}
}
return instance;
}
if (instance == null) {
synchronized (CouponManager.class) {
if (instance == null) {
instance = new CouponManager();
}
}
}
return instance;
}
//单例模式的客户端使用
public class Client {
public static void main(String[] args) {
CouponManager couponManager = CouponManager.getInstance();
}
}
在上面的代码中,使用了双重检查锁机制来保证线程安全。使用 volatile 关键字来禁止指令重排,确保在多线程环境下也能保证单例模式的正确性。
在 getInstance()方法中,首先判断 instance 是否已经被创建,如果没有,则进入 synchronized 块中再次判断 instance 是否为 null,如果为 null,
则创建一个 CouponManager 实例。由于 synchronized 关键字的性能问题,使用双重检查锁机制可以避免在每次调用 getInstance() 方法时都加锁。
同时,在 getInstance() 方法中使用了 volatile 关键字来确保对象的可见性和禁止指令重排。如果不使用 volatile 关键字,则在对象创建完成之前,
其他线程可能会读取到一个未完成初始化的对象,导致程序出现异常。
因此,在多线程环境下,双重检查锁和 volatile 关键字的组合可以保证单例模式的线程安全性和正确性。