单例模式(singleton)

本文详细介绍了单例模式的设计思想及其在Java中的实现方式,包括饿汉式和懒汉式。通过私有构造方法、静态属性和公共静态获取方法确保对象的唯一性,旨在减少内存占用并提高系统效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式(singleton)

  • 引入(设计模式要明白为什么要这样写,而不是记代码,代码很少,但记不住)

    • 设计一个系统,比如叫做百度,开发搜索引擎。代码如下:

      class Baidu{ 
        public void 搜索(String keyword){
              
          }
          
      }
      
      • 执行搜索

        • 创建一个对象

        • 写完上述代码,还不能做事情,需要调用搜索方法,才能开始搜索。

        • 同一时间有很多很多人在使用系统,数量可达到上亿。如果每个人在搜索的时候,都创建一个对象,那么需要的空间非常大,即使集群也不一定能承受得了。但是,他们创建对象目的,只是为了调用搜索方法,进行搜索。那么,想个方案,只创建一个对象,让所有人都可用,在堆内存只开辟一个空间,每调用一次方法,临时执行一次,栈内存中执行,方法执行空间就回收了。

        • 由上一条,可知,单例模式有效减少内存占用。

  • 示例

    • 不要直接在src直接创建类,即使工程就一个类,也要创建包来存放。

    • 如下代码

      SingleTon single = new SingleTon();
      
      • 这种构造对象的方式,是通过代用无参构造方法实现的。每次用过new创建对象,是通过调用构造方法得到了,如果调不到构造方法,那就创建不了独享,所以把构造方法私有,就使用new创建不了了。

      • 1.让构造方法私有—保证外面不可以随便创建对象

        private SingleTon(){
        
            }
        
      • 2.单例 不是无例—在本类中的某个成员位置上创建一个唯一对象

        • 构造方法:不行,私有 本身 调用不到

        • 块,如下方代码,在块中写,但是外面拿不到这个对象,必须要有返回值。创建了对象也无法给别人使用

          {
                SingleTon singleTon =new SingleTon()
           }
          
        • 方法,方法中可以写,但是每调用一个,创建一个,还是可以常见一个对象,保证不了唯一。

              public SingleTon xxx(){
                 SingleTon singleTon =new SingleTon();
             }
          
        • 属性:如下,但是这样写,会导致栈内存溢出(StackOverflowError,注OutOfMemory是堆内存溢出),正常来说,套娃现象应该出现的是堆内存溢出的现象,不应该是栈内存溢出,原因是开辟空间的时候,调用了构造方法(内部可以调用私有),构造方法在栈内存执行,但是一个套一个执行,栈内存不断开辟新内存块,栈内存远小于堆内存,所以先耗尽。

          public SingleTon single =new SingleTon();
          

          在这里插入图片描述

          改进上述方法

          public static SingleTon single =new SingleTon()
          

          在这里插入图片描述

          • 这时就会在方法去创建唯一一份对象,static保证对象的唯一性。

            //外部类中调用
            SingleTon s1 =SingleTon.single;
            SingleTon s2 =SingleTon.single;
            SingleTon s3 =SingleTon.single;
            //判断是不是一个对象 ==
            System.out.println(s1 ==s2) //true
            System.out.println(s1.equals(s2)) //object类继承过来,默认比地址 true String中已经重写
            
            • object中equals方法

              public boolean equals(Object obj){
                  return (this ==obj);
              }
              
          • 但是在外部类中

            SingleTon.single =null;
            
            • 这样内部类的属性指向的静态区就被截断了,之后谁也用不了了,所以public不安全,所以需要对这个属性进行一定封装。
            private static SingleTon single =new SingleTon()
            
            • 在提供一个外部获取对象的方法,方法名有个不成文的规定,get类名或者newInstance,但是这样创建会产生一个问题,使用获取对象方法之前必须要有对象,这样就拿不到对象,静态方法不需要对象,就可以调用。

              public SingleTon getSingleTon(){ 
                  return single;//引用类型
              }
              
              public static SingleTon getSingleTon(){ 
                  return single;//引用类型
              }
              
              //外部类中调用
              SingleTon s1 =SingleTon.getSingleTon();
              SingleTon s2 =SingleTon.getSingleTon();
              SingleTon s3 =SingleTon.getSingleTon();
              //判断是不是一个对象 ==
              System.out.println(s1 ==s2) //true
              System.out.println(s1.equals(s2)) //object类继承过来,默认比地址 true String中已经重写
              

              以上是单例模式的设计思想。

    • 总结:

      • 私有方法的构造方法
      • 私有静态的当前类对象作为属性
      • 公有的静态的方法返回
    • 单例实现方式

      • 饿汉式(立即加载,上面就是):对象启动时就加载,好处是不会产生对象没有就拿来使用的问题,空指针异常。不好之处启动项目加载对象过多,有些还没有使用,产生服务器承载压力问题。

        private static SingleTon single =new SingleTon() //立即加载
        public static SingleTon getSingleTon(){ 
            return single;//引用类型
        }  
        
      • 懒汉式(延迟加载):对象什么时候用到了,才会加载,坏处是由于没有操作好,导致异常,启动时候只有需要的加载,不需要的还没有创建,不会浪费空间。

        private static SingleTon single;//初始化只是一个属相,没有指向空间
        public static SingleTon getSingleTon(){
            if(single==null){
                single =new SingleTon//第一次用到,什么时候用到才会创建。
            }
            
            return single;
        }
        
      • 声明周期托管(单例对象别人帮我们处理):这个有印象即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值