Java中Singleton的3种实现方式详解

 更新时间:2021年02月21日 13:42:04   作者:pedro7  
这篇文章主要给大家介绍了关于Java中Singleton的3种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、什么是Singleton?

《设计模式》的作者、Eclipse和 Junit 的开发者 Erich Gamma 在它的理论体系中将 Singleton 定义为仅仅被实例化一次的类。在当今面向对象程序的实际开发中,Singleton 通常被用来代表一个无状态的对象,例如函数和那些本质上唯一的系统组件。

值得注意的是,使类成为 Singleton 会使得它的客户端测试变得非常困难,因为我们不可能给Singleton替换模拟实现,除非我们实现一个充当其类型的接口。

实现 Singleton 有三种常见方法,他们或是保持构造器私有并导出公有的静态成员,或是声明一个包含单个元素的枚举类型。

二、Singleton实现 —— 构造器私有

1、公有静态成员为一个final域

//Singleton with public final field 
public class Elvis { 
 public static final Elvis INSTANCE = new Elvis(); 
 pritvate Elvis() { ... } 
 public void leaveTheBuilding() { ... }
} 

在这个类中,我们仅仅拥有一个私有的构造器,它也只在初始化final域时被调用一次。由于缺少可以使用的构造器,后续的程序无法再创建 Elvis 对象。这保证了在该Java程序的整个生命周期中, Elvis 对象有且只有一个存在。

但需要注意的是,一些高权限的客户端可以借助 AccessibleObject.setAccessible 方法通过反射机制调用私有的构造器。为了避免这样的可能的攻击,可以修改构造器,让它在被要求创建第二个实例的时候抛出异常。

公有域方法的主要优势在于,API很清楚地表明了这个类是一个 Singleton ,毕竟这是一个公有的静态属性。另外,这个方法要更加简单。

2、公有静态成员为一个静态工厂方法

//Singleton with static factory
public class Elvis { 
 private static final Elvis INSTANCE = new Elvis(); 
 pritvate Elvis() { ... } 
 public static Elvis getInstance(){ return INSTANCE; }
 public void leaveTheBuilding(){ ... }
} 

显然,无论怎样调用 getInstance 方法,返回的都是同一个对象的引用。注意上面提示的反射攻击问题依然存在。

静态工厂方法有三大优势

  • 第一,它提供了更多的灵活性,在不改变API的前提下,我们可以轻易地自由调整这个类是否是Singleton。工厂方法返回该类的唯一实例,但它很容易修改成别的样子,例如为每个调用该方法的线程提供唯一实例。
  • 第二,如果程序需要,我们可以编写一个泛型 Singleton 工厂。
  • 第三,我们可以通过方法引用作为提供者,比如 Elvis::instance 就是一个 Supplier< Elvis >

(注:方法引用是Java8的一个新特性)

除非我们需要上述的其中一种优势,我们还是应该选择更简单易懂的使用公有域的方法。

3、将利用上述方法实现的Singleton类变为可序列化的

使用上述两种方法实现的 Singleton ,要把他们变成可序列化的,不能仅仅在声明中加上 implements Serializable 。为了维护并保证 Singleton ,我们必须生命所有实例域都是瞬时的,并提供一个 readResolve 方法。否则在我们每次序列化时都会创建一个新的实例。为了防止这种情况,我们要在 Elvis 类中加入如下这样的 readResolve 方法。

//readResolve method to preserve singleton property 
 private Object readResolve(){
 //Return the one true Elvis and let the garbage collector take care of the Elvis impersonator
 return INSTANCE;
 }

三、Singleton实现 —— 声明包含单个元素的枚举类型

//Enum singleton - the preferred approach
public enum Elvis{
 INSTANCE;
 public void leaveTheBuilding(){ ... }
}

这种方法在功能上与公有域方法相似,但更加简洁,无偿地提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。 虽然这种方法还没有广泛采用,但是单元素的枚举类型经常成为实现 Singleton 的最佳方法。 注意,如果 Singleton 必须扩展一个超类,而不是扩展 Enum 的时候,则不宜使用这个方法(虽然可以声明枚举去实现接口)。

总结

到此这篇关于Java中Singleton的3种实现方式的文章就介绍到这了,更多相关Java Singleton实现方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 教你在 IntelliJ IDEA 中使用 VIM插件的详细教程

    教你在 IntelliJ IDEA 中使用 VIM插件的详细教程

    这篇文章主要介绍了在 IntelliJ IDEA 中使用 VIM的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • mybatis-plus如何修改日志只打印SQL语句不打印查询结果

    mybatis-plus如何修改日志只打印SQL语句不打印查询结果

    这篇文章主要介绍了mybatis-plus如何修改日志只打印SQL语句不打印查询结果问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 通过工厂模式返回Spring Bean方法解析

    通过工厂模式返回Spring Bean方法解析

    这篇文章主要介绍了通过工厂模式返回Spring Bean方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 浅析Java BigDecimal为什么可以不丢失精度

    浅析Java BigDecimal为什么可以不丢失精度

    在金融领域,为了保证数据的精度,往往会使用BigDecimal,所以这篇文章主要来和大家探讨下为什么BigDecimal可以保证精度不丢失,感兴趣的可以了解下
    2024-03-03
  • springboot配置文件读取pom文件信息方式

    springboot配置文件读取pom文件信息方式

    这篇文章主要介绍了springboot配置文件读取pom文件信息方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Spring Boot Mail QQ企业邮箱无法连接解决方案

    Spring Boot Mail QQ企业邮箱无法连接解决方案

    这篇文章主要介绍了Spring Boot Mail QQ企业邮箱无法连接解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot日志框架如何使用

    SpringBoot日志框架如何使用

    这篇文章主要介绍了SpringBoot日志框架如何使用,帮助大家更好的理解和使用springboot日志框架,感兴趣的朋友可以了解下
    2021-01-01
  • Java基于ShardingSphere实现分库分表的实例详解

    Java基于ShardingSphere实现分库分表的实例详解

    ShardingSphere 已于2020年4月16日成为 Apache 软件基金会的顶级项目, 它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景,对ShardingSphere分库分表相关知识感兴趣的朋友一起看看吧
    2022-03-03
  • 深入理解java中的null“类型”

    深入理解java中的null“类型”

    这篇文章主要介绍了深入理解java中的null“类型”,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • java同步与异步的学习笔记整理

    java同步与异步的学习笔记整理

    在本篇文章里小编给大家整理了关于java同步与异步的学习笔记整理内容,需要的朋友们参考下。
    2020-02-02

最新评论