设计模式(单例模式)

单例模式

单例即单一的实例

1.概念

  • 指某个系统中只存在一个实例,同时提供集中统一的访问接口,以使系统行为保持协调一致。

2.饿汉单例

2.1 场景

  • 适用严格把控对象实例化的过程。

2.2 设计思路

  • 第一,确保任何人都不能创建对象实例,禁止外部调用构造器,将对象构造器私有化。

  • 第二,让对象自己创建自己,使其自有永久拥有自己,将对象自己实例化并使用。

    • private关键字保证对象实例的私有性、不可见性、不可访问性。

    • static关键字确保对象的静态性,并在类加载时即初始化,与类同在。该实例在内存中永生,内存垃圾收集器(GC)也不会对其进行回收。

    • final关键字确保对象实例是常量,一旦引用被赋值后不能在修改。

  • 第三,提供外部访问接口。

    • 提供一个静态getInstance()来获取对象的单例对象。

    • 设置public关键字暴露,以供外部使用。

2.3 范例

  • 饿汉造日

    
       package singleton;
       
       /**
        * @author huangdq
        * @version 1.0.0
        * @ClassName Sun.java
        * @Description 太阳
        * @createTime 2022年03月24日 10:20:00
        */
       public class Sun {
       
           // 自有永有单例
           public static final Sun sun = new Sun();
       
           // 构造器私有化
           private Sun(){
       
           }
       
           // 方法公开化
           public static Sun getInstance(){
               return sun;
           }
       }
    
    

3.懒汉单例

3.1 场景

  • 适用严格把控对象实例化的过程。

3.2 设计思路

  • 第一,确保任何人都不能创建对象实例,禁止外部调用构造器,将对象构造器私有化。

  • 第二,创建对象,并且将其私有和静态化处理,但不做实例化处理。

    • private关键字保证对象实例的私有性、不可见性、不可访问性。

    • volatile关键字确保变量值在各线程访问时的同步性、唯一性。

    • static关键字确保对象的静态性,并在类加载时即初始化,与类同在。该实例在内存中永生,内存垃圾收集器(GC)也不会对其进行回收。

  • 第三,在判空后,加入同步锁synchronized以防止多线程多次实例化线程。

3.3 扩展

  • 懒加载的“双检锁”

    • 这里共采用2个判空嵌套,外层放宽入口,保证线程并发的高效性;内层加锁同步保证实例化的单次运行。不仅达到单例模式的效果还保证运行效率。
  • 反例

       package singleton;
       
       /**
        * @author huangdq
        * @version 1.0.0
        * @ClassName Sun.java
        * @Description 太阳
        * @createTime 2022年03月24日 10:20:00
        */
       public class Sun {
       
           // 先不进行实例化
           public static Sun sun;
       
           // 构造器私有化
           private Sun() {
       
           }
       
           // 方法公开化
           public static synchronized Sun getInstance() {
               // 过滤多线程中无日对象
               if (sun == null) {
                   sun = new Sun();
               }
               return sun;
           }
       }
    
    
    • 该方法也能实现懒汉设计模式,但这种做法一直进行加锁排队,会造成线程堵塞,造成资源和时间浪费。

3.4 范例

  • 懒汉造日

   package singleton;
   
   /**
    * @author huangdq
    * @version 1.0.0
    * @ClassName Sun.java
    * @Description 太阳
    * @createTime 2022年03月24日 10:20:00
    */
   public class Sun {
   
       // 先不进行实例化
       public volatile static Sun sun;
   
       // 构造器私有化
       private Sun(){
   
       }
   
       // 方法公开化
       public static Sun getInstance(){
           // 过滤多线程中无日对象
           if (sun == null) {
               // 加锁排队,只需造一个日,保证单例
              synchronized (Sun.class){
                  if (sun == null){
                      sun = new Sun();
                  }
              }
           }
           return sun;
       }
   }

4. 二者对比

  • ”饿汉模式“使用静态常量实例化,一般随着类加载而进行实例创建,浪费内存空间;但”饿汉模式“初始化较快,节省CPU资源消耗。

  • ”懒汉模式“节省内存空间,在需要调用实例后才进行创建,不会造成内存浪费,但是初始化较慢,并且需要注意多并发场景的影响,在并发下考虑加锁等浪费资源,也造成CPU的浪费。

  • 简而言之,我们更加偏向使用”饿汉模式“设计

5. 运用场景

  • spring 框架 IOC容器 业务对象管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值