单例模式的懒汉式,饿汉式详解

什么是单例模式?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式的优缺点:

优点

  • 在内存中只有一个实例对象,减少内存开销。解决了频繁创建和销毁内存实例对象的问题。
  • 避免过多的资源占用。比如:写文件操作

缺点:

  • 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

单例设计模式分类

单例模式主要分为,懒汉式和饿汉式。更为具体的就是:普通懒汉式单例模式、同步锁懒汉式单例模式、同步代码块懒汉式案例模式、饿汉式单例模式、双重校验锁(双检锁)单例模式、静态内部类(登记式)单例模式和枚举单例模式。

懒加载的必要性

并不是什么时候都需要用到单例去创造实体,会造成资源的浪费和内存的占用。虽然占用的不多,但是也是一种漏洞。所以我们就需要一种只有使用的时候才去创建的方式(Lazy Load)懒加载

懒加载(Lazy Load),这里的懒加载指的是在使用实例对象的时候才会去创建实例对象。这就避免了资源的浪费和内存的占用问题。其实懒加载无非就是在空间换时间与时间换空间中的取舍!

单例模式:

废话不多说了,直接上代码,更为直观的了解一下

普通懒汉式

//普通懒汉式单例模式(线程不安全)
class Singleton {
    //创建实例对象
    private static Singleton instance = null;

    //私有化构造器
    private Singleton() {

    }

    //提供static修饰的get方法,以供外界创建实例对象
    public static Singleton getInstance() {
        //判断实例对象是否为空,为空则创建实例对象并返回
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

 同步锁懒汉

//同步锁懒汉式单例模式(线程安全)
class Singleton {
    //创建实例对象
    private static Singleton instance = null;

    //私有化构造器
    private Singleton() {

    }

    //加同步锁并被static修饰的get方法
    public synchronized static Singleton getInstance() {
        //具体来说以下是原子操作
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

 饿汉式

/**
 * 饿汉式单例
 * 线程安全问题:天生线程安全(无锁)
 * 不支持懒加载,类加载的时候就创建好了实例,占用资源
 * 效率高
 *
 */
class Singleton {
	//在类的内部创建一个类的实例,该静态修饰的对象随着类加载只会创建一次实例
	private static final Singleton instance=new Singleton();
	private Singleton() {
		
	}
	//私有化对象,使只能通过公有方法调用
	//提供公共的get方法,只能通过类来调用,因为设置了static的,同时获取实体也需要设置成静态的
	public static Singleton getInstance() {
		
		return instance;
	}
}

双检锁模式

/**
 * 双检锁单例
 * 双检锁设计思想:单实例对象需要创建好一次以后反复使用,保证了在第一次创建对象的时候线程安全
 * 以后就不用再重新创建对象,判断不为空直接返回实例对象即可,安全又高效
 * 线程安全:原子操作+同步代码块
 * 懒加载,支持,使用时创建实例
 * 效率高
 *
 */
class Singleton1 {
	//创建实例对象
	private static Singleton1 instance=null;
	private Singleton1() {
		
	}
	//私有化对象,使只能通过公有方法调用
	//提供公共的get方法,只能通过类来调用,因为设置了static的,同时获取实体也需要设置成静态的
	public static Singleton1 getInstance() {
		//初始判断是否为空
		if(instance==null) {
			//同步代码块锁实例对象
			synchronized (Singleton1.class) {
				//以下为原子操作
				if(instance==null) {
					instance=new Singleton1();
				}
			}
		}
		return instance;
	}
}

静态内部类

/**
 * 静态内部类
 *思想:使用静态内部类实例对象,不会在类加载的时候创建,而且静态保证了线程安全,使用的时候返回静态内部类调用的实例对象即可
 * 线程安全:安全的,静态内部类调用对象保证了线程安全
 * 懒加载,支持,使用时创建实例
 * 效率高
 *
 */
class Singleton2 {
	//编写静态内部类创建实例
	private static  class Singleton2Holder {
		private static final Singleton2 instance=new Singleton2();
	}
	//私有化对象,使只能通过公有方法调用
	private  Singleton2() {
		
	}
	
	//提供公共的get方法,只能通过类来调用,因为设置了static的,同时获取实体也需要设置成静态的
	public static Singleton2 getInstance() {

		return Singleton2Holder.instance;
	}
}

枚举单例

/**
 * 
 * 枚举单例模式
 *天生可避免反射和序列化攻击
 *线程安全,但不支持懒加载
 *效率高
 */
public enum Singleton3{
	instance
}

猜你喜欢

转载自blog.csdn.net/qq_36542426/article/details/106382019