单例模式(懒汉式和饿汉式区别)

单例模式

所谓单例模式,就是保证类在内存中只有一个对象

而如何保证类在内存中只有一个对象?

思考一下,我们平时在实例化类的对象时,基本都是通过new 的方式来实例化一个对象,其实说白了,就是调用了需要实例化类的默认的构造方法,所以为了保证类只有一个对象,我们需要将类的对象设置为private

1)控制类的创建,不让其他类创建本类的对象,即需要设置private属性

2)在本类中定义一个本类的对象

public class test {

	public static void main(String[] args) {
		//分别实例化对象 s1,s2
		Singleton s1 = Singleton.singleton;
		Singleton s2 = Singleton.singleton;
		System.out.println(s1 == s2);
	}

}
class Singleton{
	//私有的构造函数,保证外类不能实例化本类
	private Singleton(){}
	//自己创建一个类的实例化
	public static Singleton singleton  = new Singleton();
}

在这里输出一下,看一看s1和s2是不是引用的同一个实例s的地址

结果为true,可以看出,通过创建私有构造函数这样是可以保证单例的

但是,会有一个问题!!

public class test {

	public static void main(String[] args) {
		//分别实例化对象 s1,s2
		Singleton s1 = Singleton.singleton;
		//这里突然 将Singleton中的变成了null
		Singleton.singleton = null;
		Singleton s2 = Singleton.singleton;
		System.out.println(s1 == s2);
	}

}
class Singleton{
	//私有的构造函数,保证外类不能实例化本类
	private Singleton(){}
	//自己创建一个类的实例化
	public static Singleton singleton = new Singleton();
}

在执行main方法的时候,突然有个进程插了进来,将Singleton中的s变成了null(多线程中,很常见),这时就相当于引用了两个地址,即不符合了单例的定义

所有,只用private设置构造函数是不够的,为此,还需要进行第三步

3)提供公共的访问方式

public class test {

	public static void main(String[] args) {
		//分别实例化对象 s1,s2
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}

}
class Singleton{
	//私有的构造函数,保证外类不能实例化本类
	private Singleton(){}
	//自己创建一个类的实例化
	private static Singleton singleton = new Singleton();
	//创建一个get方法,返回一个实例s
	public static Singleton getInstance(){
		return singleton;
	}
}

先将Sinleton类中的实例化私有(private),使得外界不能调用,然后创建要给get方法,返回一个实例s,这样,就保证了在外类中不能更改s的值,即保证了单例的实现

其实上述的方式 就是单例模式中的饿汉式

所谓饿汉式,就是直接创建出类的实例化;

而对于懒汉式,就是在需要的时候再创建类的实例化

class Singleton {
	// 私有的构造函数,保证外类不能实例化本类
	private Singleton() {
	}

	// 自己创建一个类的实例化
	private static Singleton singleton;

	// 创建一个get方法,返回一个实例s
	public static Singleton getInstance(){
		//判断singleton是否为null,如果为null,即判定需要实例化
		if (singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

对于懒汉式,就是在getInstance方法中增加一个if判断,判断当前对象是否为null,如果为null,则创建实例

===============================分割线=============================================

这里来进行一个比较,究竟饿汉式和懒汉式哪一个更好;

饿汉式:简单来说就是空间换时间,因为上来就实例化一个对象,占用了内存,(也不管你用还是不用)

懒汉式:简单的来说就是时间换空间,与饿汉式正好相反

这时,会有人说,懒汉式比饿汉式更好,其实恰恰相反,这里举个例子!

public static Singleton getInstance(){
		//判断singleton是否为null,如果为null,即判定需要实例化
		if (singleton == null) {
			//
			
			singleton = new Singleton();
		}
		return singleton;
	}

比如,现在有A线程和B线程,A线程刚好在这个getInstance()方法中,刚刚判断完非空(此时为null),即需要创建实例,然而,就是这么巧,B线程抢到了CPU的执行权,A线程sleep了,这时,B线程也进行了这个判断,和A一样,都需要创建实例,而这时,A也抢到了CPU,这时,B就sleep了,然后A执行了实例化后,B又抢到CPU执行权,然后B也实例化,这时,出现问题了,A和B都实例化了一个对象,这就是赤果果的两个对象呀,单例呢,唯一呢,全都没了。

而且,上面说过,懒汉式和饿汉式的区别具体就是时间和空间的转换,现在开发的时候关心的应该还是时间,对于空间,完全可以通过硬件来优化呀,加大内存!!!但是减少时间计算就很麻烦了,额!!

所以说,对于懒汉式在多线程中式不支持的(仅个人观点,毕竟我的水平还不熟练),所以相对来说,更多的是用饿汉式

===============================分割线=============================================

之前百度单例的时候,发现还有第三种方法,简单试了一下,也能达到单例的效果,但是没有具体尝试,这里粘个代码和运行结果看看就好了

public class test {

	public static void main(String[] args) {
		// 分别实例化对象 s1,s2
		Singleton s1 = Singleton.singleton;
		// 在这里 更改singleton的值是不允许的,因为设置了final属性
		// Singleton.singleton = null;
		Singleton s2 = Singleton.singleton;
		System.out.println(s1 == s2);
	}
}

class Singleton {
	// 私有的构造函数,保证外类不能实例化本类
	private Singleton() {
	}

	// 自己创建一个类的实例化
	public static final Singleton singleton = new Singleton();

}

其实这种方法就是将singleton类中实例化方法加了一个final属性,就是不允许更改其值,所以在外类进行对其进行修改时,是不会允许的,同样达到了单例的效果。

  • 22
    点赞
  • 128
    收藏
    觉得还不错? 一键收藏
  • 22
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值