23种设计模式-单例模式

23种设计模式-单例模式

产生背景

某些情况,如:线程池,一个项目中总线程数量以及生命周期,可能需要统一控制;如果线程池自身可创建多个实例,那么就无法统一控制,此时,只要能控制线程池对象的数量为一个,那么就可以实现统一控制的目标;

注意:现实中真正使用纯的单例模式并不多;
如:spring bean ,通过配置来决定是否使用单例;线程池、连接池也并未使用单例(如果完全使用单例,就没办法根据业务配置多个线程池和多数据源连接池)

概念

整个项目或系统的生命周期内,只创建一个对象;

原理

本质:
更像是一个能创建类自身实例的工具类;
  • 关闭构造器

    防止外部类通过new 创建实例

  • 类内部创建一个实例

    逻辑由内部实现;

  • 对外只提供一个获取实例的 静态 方法

    对外提供使用接口;

使用场景

只能创建一个对象的场景

实现方式

  • 懒汉模式
概念相关:
所谓懒,就是在需要时才创建,不需要就不创建;所谓的需要就是调用;
优点:
第一次调用时产生对象,不需要提前创建一个可能永不使用的对象;
缺点:
创建时存在锁竞争;使用时需要null检查;
public class SingleModel{
    //关闭构造器,防止通过new 创建
    private SingleModel(){}
    public static SingleModel getInstance(){
       //第一次判断,防止进入锁判断
       if (null == INSTANCE){
           //加锁
           synchronized (INSTANCE){
               //二次判断,防止并发操作:多个线程同时竞争锁,第一个执行结束释放锁后,第二个进程等待获取锁后,又重新创建一次对象;
               if (null == INSTANCE){
                   INSTANCE = new SingleModel();
               }
           }
       }
       return INSTANCE;
    }
}
  • 饿汉模式
概念相关
所谓饿,就是在需要对象之前就已经创建,需要时直接返回已经创建的对象即可;
优点:
使用时,不需要每次都进行null检查,和锁竞争;减小性能消耗;
缺点:
提前创建对象,可能对象永远不会使用;
public class SingleModel{
    //关闭构造器,防止通过new创建对象
    private SingleModel(){}
    //类加载时创建:通过类加载的线程安全特性创建实例
    private static final SingleModel INSTANCE = new SingleModel();

    //直接返回实例
    public static SingleModel getInstance(){
       return INSTANCE;
    }
}
  • 折中模式
优点:
集成了懒汉和饿汉的所有优点;对象延迟创建;线程安全,无需要检查和加锁;
原理:
A:类在第一次使用时才会加载(import并不会加载)
B:类加载本身是线程安全的
C:内部类可以调用外部类的私有构造器
D:通过内部类的延迟加载,实现实例的延迟创建;通过内部类加载的线程安全性,创建静态属性引用外部对象;
public class SingleModel{
    //关闭构造器,防止通过new创建对象
   private SingleModel(){}

   //内部类:静态属性-引用外部对象
   private static class SingleInstanceModel{
       private static final SingleModel INSTANCE = new SingleModel();
   }

   //第一调用时,才开始加载内部类,又通过内部类(类加载的线程安全性)的加载,生成外部对象;
   public static SingleModel getInstance(){
       return SingleInstanceModel.INSTANCE;
   }

实际场景

主要开源项目中,真正使用纯的单例模式的例子并不多。

猜你喜欢

转载自blog.csdn.net/yangspgao/article/details/80470713