设计模式之单例模式Java代码示例

  • 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,属于创建型模式。

  • 核心作用:

    • 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
  • 常见场景

    • Windows系统任务管理器
    • Windows系统回收站
    • 项目中,读取配置文件的类,一般也只有一个对象,没必要每次用new实例化对象读取。
    • 网站的计数器一般也会采用单例模式,可以保证同步
    • 数据库连接池的设计一般也是单例模式
    • 在Servlet编程中,每个Servlet也是单例的
    • 在Spring中,每个Bean默认就是单例的
    • ...........
  • 优点:

    • 由于单例模式只生成一个实例,减少了系统性能开销。
    • 单例模式可以在系统设置全局的访问点,优化共享资源访问。
    • 单例模式可以说是一个合格的开发都会写。但是如果要深究,小小的单例模式可以牵涉到很多东西。
  • 缺点:

    • 没有定义接口,不可继承,与单一职责原则相冲突,类只应该关心其内部逻辑,不关心外面怎么去实例化。
  • 如何去保证实例唯一

    • 防止类外部被初始化
    • 由类自身进行实例化
    • 保证类仅实例化一次
    • 对外提供获取该实例的唯一方法
    • 线程安全
  • 常见的五种单例模式实现方式

    • 饿汉式(线程安全,调用效率高,不能延时加载)

      //饿汉式单例
      public class SingletonDemo01 {
      
          //1.私有化构造器
          private SingletonDemo01(){
          }
          //2.类初始化的时候,立即加载该对象
          private static SingletonDemo01 instance = new SingletonDemo01();
          //3.提供获取该对象的方法,没有synchronized,效率高!
          public static SingletonDemo01 getInstance(){
              return instance;
          }
      
      }
      
      class SingletonDemo01Test{
          public static void main(String[] args) {
              SingletonDemo01 instance = SingletonDemo01.getInstance();
              SingletonDemo01 instance2 = SingletonDemo01.getInstance();
              System.out.println(instance==instance2);//true
          }
      }
      
    • 懒汉式(线程安全,调用效率不高,可以延时加载)

      //懒汉式
      public class SingletonDemo02 {
          //1.私有化构造器
          private SingletonDemo02(){
          }
          //2.类初始化的时候,不立即加载该对象
          private static SingletonDemo02 instance;
      
          //3.提供获取该对象的方法,有synchronized,效率较低!
          public static synchronized SingletonDemo02 getInstance(){
              if(instance == null){
                  instance = new SingletonDemo02();
              }
              return instance;
          }
      }
      
      
      class SingletonDemo02Test{
          public static void main(String[] args) {
              SingletonDemo02 instance = SingletonDemo02.getInstance();
              SingletonDemo02 instance2 = SingletonDemo02.getInstance();
              System.out.println(instance==instance2);//true
          }
      }
      
    • DCL懒汉式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)

      //DCL 双检锁/双重校验锁(DCL,即 double-checked locking) 懒汉式
      public class SingletonDemo03 {
          private static boolean flag = false;
      
          //1.私有化构造器
          private SingletonDemo03(){
              synchronized (SingletonDemo03.class){
                  if(flag == false){
                      flag = true;
                  }else{
                      throw new RuntimeException("不要试图用反射破坏我们的单例");
                  }
              }
          }
          //2.类初始化的时候,不立即加载该对象
          //volatile 原子性
          private volatile static SingletonDemo03 instance;
      
          //3.提供获取该对象的方法,有synchronized,效率较低!
          public static  SingletonDemo03 getInstance(){
              if(instance == null){
                  synchronized (SingletonDemo03.class){
                      if(instance == null){
                          instance = new SingletonDemo03();
                      }
                  }
      
              }
              return instance;
          }
      
      }
      
      
      class SingletonDemo03Test{
          public static void main(String[] args) throws Exception {
      
              Constructor<SingletonDemo03> declaredConstructor = SingletonDemo03.class.getDeclaredConstructor(null);
              declaredConstructor.setAccessible(true);
              SingletonDemo03 instance1 = declaredConstructor.newInstance();
              SingletonDemo03 instance3 = declaredConstructor.newInstance();
              System.out.println(instance1==instance3);
              System.out.println(instance1.hashCode());
              System.out.println(instance3.hashCode());
          }
      }
      
    • 饿汉式改进:静态内部类(线程安全,调用效率高,可以延迟加载)

      //静态内部类实现
      public class SingletonDemo04 {
      
          private SingletonDemo04(){ }
      
          private static class InnerClass{
              private static final SingletonDemo04 instance = new SingletonDemo04();
          }
      
          public static SingletonDemo04 getInstance(){
              return InnerClass.instance;
          }
      
      }
      //反射机制:可以破坏以上的单例
      class SingletonDemo04Test{
          public static void main(String[] args) throws Exception {//捕获一个大异常Exception
              SingletonDemo04 instance = SingletonDemo04.getInstance();
      
              Constructor<SingletonDemo04> declaredConstructor = SingletonDemo04.class.getDeclaredConstructor(null);
              declaredConstructor.setAccessible(true);
              SingletonDemo04 instance3 = declaredConstructor.newInstance();
              System.out.println(instance==instance3);
              System.out.println(instance.hashCode());
              System.out.println(instance3.hashCode());
          }
      }
      
    • 枚举单例(线程安全,调用效率高,不能延迟加载)

      public enum SingletonDemo05 {
          INSTANCE;
      
          public SingletonDemo05 getInstance(){
              return INSTANCE;
          }
      }
      class SingleDemo05Test{
          public static void main(String[] args) {
              SingletonDemo05 instance = SingletonDemo05.INSTANCE;
              SingletonDemo05 instance2 = SingletonDemo05.INSTANCE;
              System.out.println(instance==instance2);
          }
      }
      

      (本篇知识杂柔自互联网,仅供分享学习)

04-25 22:07