设计模式-单例模式

翻译自java-design-patterns

目的

确保一个类只有一个实例,并且提供一个全局访问点。

说明

例子

只有一个象牙塔可以让巫师学习他们的魔法。巫师总是使用同样的魔法象牙塔。这个象牙塔就是单例。

简单的说

确保只创建一个特定类的一个对象。

维基百科

在软件工程中,单例模式是一种软件设计模式,它将一个类的实例化限制为一个对象。对于需要确切的一个对象来协调系统中的操作时是非常有用的。

代码示例

实现单例的最好方式就是单个元素的枚举类

public enum EnumIvoryTower {
  INSTANCE;
}
EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE;
EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE;
assertEquals(enumIvoryTower1, enumIvoryTower2); // true
复制代码

恶汉式单例模式

public final class IvoryTower {

  /**
   * 私有构造器,所以外部无法实例化该类
   */
  private IvoryTower() {}

  /**
   * 静态实例.类加载完之后被实例
   */
  private static final IvoryTower INSTANCE = new IvoryTower();

  /**
   * 调用此方法获取单例.
   *
   * @return 单例.
   */
  public static IvoryTower getInstance() {
    return INSTANCE;
  }
}
复制代码

懒汉式单例

在Java中Initialize-on-demand-holder idiom 创建懒加载单例是一种安全的方式。当getInstance()调用时,内部类还没有被加载。而类加载是安全的,因此,这种解决方案是线程安全的,尽管没有使用volatile或者synchronized。

public final class InitializingOnDemandHolderIdiom {

  /**
   * 私有构造器.
   */
  private InitializingOnDemandHolderIdiom() {}

  /**
   * @return 单例
   */
  public static InitializingOnDemandHolderIdiom getInstance() {
    return HelperHolder.INSTANCE;
  }

  /**
   * 提供懒加载单例
   */
  private static class HelperHolder {
    private static final InitializingOnDemandHolderIdiom INSTANCE =
        new InitializingOnDemandHolderIdiom();
  }
}
复制代码

线程安全懒汉单例

实例被懒加载,因此需要同步机制。

public final class ThreadSafeLazyLoadedIvoryTower {

  private static ThreadSafeLazyLoadedIvoryTower instance;

  private ThreadSafeLazyLoadedIvoryTower() {
    //防止被反射
    if (instance == null) {
      instance = this;
    } else {
      throw new IllegalStateException("Already initialized.");
    }
  }

  /**
   * 当第一次调用时实例才会被创建,但是由于每次调用都有锁,性能不好
   */
  public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() {
    if (instance == null) {
      instance = new ThreadSafeLazyLoadedIvoryTower();
    }

    return instance;
  }
}
复制代码

线程安全双重检查单例

public final class ThreadSafeDoubleCheckLocking {

  //内存可见,防止重排
  private static volatile ThreadSafeDoubleCheckLocking instance;

  /**
   * 私有构造防止被外部实例化
   */
  private ThreadSafeDoubleCheckLocking() {
    // 防止被反射
    if (instance != null) {
      throw new IllegalStateException("Already initialized.");
    }
  }

  /**
   * 公共访问
   *
   * @return 实例
   */
  public static ThreadSafeDoubleCheckLocking getInstance() {

    ThreadSafeDoubleCheckLocking result = instance;
    // 检查是否被实例化,如果已经实例化则返回实例
    if (result == null) {
      // 有可能在其它线程初始化了
      // 所以为了确保我们需要锁定一个对象来实现互斥。
      synchronized (ThreadSafeDoubleCheckLocking.class) {
        // 再次将实例赋值给局部变量以检查它是否被其他线程初始化
        // 而当前线程被阻止进入锁定区域. 如果它已被初始化,那么我们可以返回之前创建的实例,就像之前的空检查一样。
        result = instance;
        if (result == null) {
          //实例还是没有被创建(其它线程无法进入),所以我们可以安全地创建实例并且赋值给instance和result。
          instance = result = new ThreadSafeDoubleCheckLocking();
        }
      }
    }
    return result;
  }
}
复制代码

典型用例

  • the logging class
  • managing a connection to a database
  • file manager
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值