博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式-单例模式
阅读量:7106 次
发布时间:2019-06-28

本文共 2876 字,大约阅读时间需要 9 分钟。

翻译自

目的

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

说明

例子

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

简单的说

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

维基百科

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

代码示例

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

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

转载地址:http://wxvhl.baihongyu.com/

你可能感兴趣的文章
MyClouds开发指南》第1章 MyClouds微服务治理及快速开发平台简介
查看>>
用JDK制作可能运行的JAR
查看>>
开发人员如何转型做产品经理
查看>>
SVN 基本命令
查看>>
RTP协议分析
查看>>
boost_asio学习笔记[2] - 客户端异步通讯
查看>>
lucene全文搜索之排序
查看>>
SpringBoot之数据访问
查看>>
iOS逆向问题集锦
查看>>
python正则提取特定标签内的字符
查看>>
转:Android屏幕适配经验谈
查看>>
jquery ajax get post 的使用方法汇总
查看>>
50个必备的实用jQuery代码段
查看>>
网站安装打包 修改app.config[六]
查看>>
git 安装使用
查看>>
hive 分区表、桶表和外部表
查看>>
eclipse查看java方法域
查看>>
Linux系统究竟我要怎样学?
查看>>
正在学习linux的我写一封信给十年后的自己
查看>>
利用scp 远程上传下载文件/文件夹
查看>>