设计模式系列之单例模式(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中,其他的地方均可以合理利用。

posted @ 2019-02-15 10:32  燕归来兮  阅读(124)  评论(0编辑  收藏  举报