• 设计模式系列之单例模式(Singleton Pattern)


    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    • 1、单例类只能有一个实例。
    • 2、单例类必须自己创建自己的唯一实例。
    • 3、单例类必须给所有其他对象提供这一实例。

    单例模式的创建方式,主要有四种:

    • 饿汉模式
    • 懒汉模式
      • 普通模式
      • 懒汉模式
      • 双重校验锁

    饿汉模式

    顾名思义,就是非常的饥饿,立即的创建单例模式。

    public class HungrySingleton {
    
      //饿汉模式,立即创建对象
      private static HungrySingleton hungrySingleton = new HungrySingleton();
    
      /** 私有化构造方法 */
      private HungrySingleton() {}
    
      /**
       * 获取单例实例
       *
       * @return
       */
      public static HungrySingleton getInstance() {
        rturn hungrySingleton;
      }
    }
    

    这种模式具有以下特点:

    • 线程安全,避免了多线程同步问题
    • 没有达到懒加载的效果

    懒汉模式

    懒汉模式,就在在创建实例的时候不初始化,待到需要获取实例对象的时候在判断,是不是尚未实例化,是的话进行实例化对象,然后返回,否则直接返回简单的懒汉模式如下:

    public class LazySingleton {
    
      private static LazySingleton lazySingleton = null;
    
      /** 私有化构造方法 */
      private LazySingleton() {}
    
      /**
       * 获取单例实例
       *
       * @return
       */
      public static LazySingleton getInstance() {
    	  //检查判断,没有初始化的时候尝试初始化
        if (lazySingleton == null) {
          lazySingleton = new LazySingleton();
        }
        return lazySingleton;
      }
    }
    

    虽然这种模式能够达到懒加载的目的,提高了性能,但是线程不安全,无法避免多线程的问题,在多线程的操作下,可能会出现实例化多个对象的情况,违反了单例的约束条件。

    所以我们可以为初始化添加校验锁,如下:

    public class LazySyncSingleton {
    
      private static LazySyncSingleton lazySyncSingleton = null;
    
      /** 私有化构造方法 */
      private LazySyncSingleton() {}
    
      /**
       * 获取单例实例
       *
       * <p>添加了 synchronized 锁机制
       *
       * @return
       */
      public static synchronized LazySyncSingleton getInstance() {
        if (lazySyncSingleton == null) {
          lazySyncSingleton = new LazySyncSingleton();
        }
        return lazySyncSingleton;
      }
    }
    
    

    但是需要注意的是,我们初始化只在第一次调用hetInstance的时候,尝试初始化,后期我们都是直接返回对象,假设我们创建好了对象,存在多个线程获取对象,那么每个线程都要等待其他线程执行完成之后在执行获取实例,这种设计模式,性能非常低,因此我们利用DCL(Double Check Lock,双重校验锁)来实现

    public class DoubleCheckLockSingleton {
    
      private static volatile DoubleCheckLockSingleton doubleCheckLockSingleton;
    
      private DoubleCheckLockSingleton() {}
    
      private static DoubleCheckLockSingleton getInstance() {
        if (doubleCheckLockSingleton == null) {
          synchronized (DoubleCheckLockSingleton.class) {
            if (doubleCheckLockSingleton == null) {
              doubleCheckLockSingleton = new DoubleCheckLockSingleton();
            }
          }
        }
        return doubleCheckLockSingleton;
      }
    }
    

    DCL机制是一个非常好的设计理念,不仅仅只用在Sign'leton Pattern中,其他的地方均可以合理利用。

  • 相关阅读:
    判断用户 是用的电脑还是手机 判断 是安卓还是IOS
    特殊符号
    如何在 ajax 外拿到 ajax 的数据???和ajax的参数
    事件(只有事件 没有其他)
    c3 新特性
    jquery 操作属性[选择器为主]
    按字母排序,sql语句查询法
    ubuntu12.04安装lamp的简单lamp
    Ubuntu 下傻瓜式安装配置lamp环境
    万能HTML编辑框 CuteEditor 使用详解
  • 原文地址:https://www.cnblogs.com/zhoutao825638/p/10382172.html
Copyright © 2020-2023  润新知