单例模式之懒汉式与饿汉式

单例模式

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

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

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

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

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

  1. public class test {
  2. public static void main(String[] args) {
  3. //分别实例化对象 s1,s2
  4. Singleton s1 = Singleton.singleton;
  5. Singleton s2 = Singleton.singleton;
  6. System.out.println(s1 == s2);
  7. }
  8. }
  9. class Singleton{
  10. //私有的构造函数,保证外类不能实例化本类
  11. private Singleton(){}
  12. //自己创建一个类的实例化
  13. public static Singleton singleton = new Singleton();
  14. }

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

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

但是,会有一个问题!!

  1. public class test {
  2. public static void main(String[] args) {
  3. //分别实例化对象 s1,s2
  4. Singleton s1 = Singleton.singleton;
  5. //这里突然 将Singleton中的变成了null
  6. Singleton.singleton = null;
  7. Singleton s2 = Singleton.singleton;
  8. System.out.println(s1 == s2);
  9. }
  10. }
  11. class Singleton{
  12. //私有的构造函数,保证外类不能实例化本类
  13. private Singleton(){}
  14. //自己创建一个类的实例化
  15. public static Singleton singleton = new Singleton();
  16. }

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

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

3)提供公共的访问方式

  1. public class test {
  2. public static void main(String[] args) {
  3. //分别实例化对象 s1,s2
  4. Singleton s1 = Singleton.getInstance();
  5. Singleton s2 = Singleton.getInstance();
  6. System.out.println(s1 == s2);
  7. }
  8. }
  9. class Singleton{
  10. //私有的构造函数,保证外类不能实例化本类
  11. private Singleton(){}
  12. //自己创建一个类的实例化
  13. private static Singleton singleton = new Singleton();
  14. //创建一个get方法,返回一个实例s
  15. public static Singleton getInstance(){
  16. return singleton;
  17. }
  18. }

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

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

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

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

  1. class Singleton {
  2. // 私有的构造函数,保证外类不能实例化本类
  3. private Singleton() {
  4. }
  5. // 自己创建一个类的实例化
  6. private static Singleton singleton;
  7. // 创建一个get方法,返回一个实例s
  8. public static Singleton getInstance(){
  9. //判断singleton是否为null,如果为null,即判定需要实例化
  10. if (singleton == null) {
  11. singleton = new Singleton();
  12. }
  13. return singleton;
  14. }
  15. }

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

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

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

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

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

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

  1. public static Singleton getInstance(){
  2. //判断singleton是否为null,如果为null,即判定需要实例化
  3. if (singleton == null) {
  4. //
  5. singleton = new Singleton();
  6. }
  7. return singleton;
  8. }

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

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

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

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

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

  1. public class test {
  2. public static void main(String[] args) {
  3. // 分别实例化对象 s1,s2
  4. Singleton s1 = Singleton.singleton;
  5. // 在这里 更改singleton的值是不允许的,因为设置了final属性
  6. // Singleton.singleton = null;
  7. Singleton s2 = Singleton.singleton;
  8. System.out.println(s1 == s2);
  9. }
  10. }
  11. class Singleton {
  12. // 私有的构造函数,保证外类不能实例化本类
  13. private Singleton() {
  14. }
  15. // 自己创建一个类的实例化
  16. public static final Singleton singleton = new Singleton();
  17. }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值