代码简洁 这是迄今为止最大的优点,如果你曾经在Java5之前写过单例模式代码,那么你会知道即使是使用双检锁你有时候也会返回不止一个实例对象。
虽然这种问题通过改善java内存模型和使用volatile变量可以解决,但是这种方法对于很多初学者来说写起来还是很棘手。
相比用 synchronization的双检锁实现方式来说,枚举单例就简单多了。
你不相信?比较一下下面的双检锁实现代码和枚举实现代码就知道了。 注:文末有福利!

用枚举实现的单例:

这是我们通常写枚举单例的方式,它可能包含实例变量和实例方法,但是简单来说我什么都没用,需要注意的是如果你使用实例方法,你就需要确保方法的线程安全性,避免它会影响对象的状态。通常情况下枚举里面创建实例是线程安全的,但是其它的方法就需要编程者自己去考虑了。

public enum EasySingleton{
INSTANCE;
}

代码就这么简单,你可以使用EasySingleton.INSTANCE调用它,比起你在单例中调用getInstance()方法容易多了。

用双检索实现单例:

下面的代码是用双检索实现单例模式的例子,在这里getInstance()方法检查了两次来判断INSTANCE是否为null,这就是为什么叫双检索的原因,记住双检索在java5之前是有问题的,但是java5在内存模型中有了volatile变量之后就没问题了。

public class DoubleCheckedLockingSingleton{
private volatile DoubleCheckedLockingSingleton INSTANCE; private DoubleCheckedLockingSingleton(){} public DoubleCheckedLockingSingleton getInstance(){
if(INSTANCE == null){
synchronized(DoubleCheckedLockingSingleton.class){
//double checking Singleton instance
if(INSTANCE == null){
INSTANCE = new DoubleCheckedLockingSingleton();
}
}
}
return INSTANCE;
}
}

你可以访问DoubleCheckedLockingSingleTon.getInstance()来获得实例对象。

现在看看二者创建一个懒加载线程安全的单例需要的代码数量。
使用枚举单例模式你只需要一行代码搞定因为枚举实例的创建是线程安全的。

你可能会说比起使用双检索方法还有更好的方法实现单例模式,但是任何一种方法都有它的利和弊,就像我下面例子中展示的我很喜欢的一种在类加载期间初始化静态域的单例实现方式,但是要记住这不是一种懒加载单例方式。

用静态工厂方法实现单例:

这是java中我比较喜欢的一种实现单例模式的方法,由于单例实例是static和final的,当类第一次被加载到内存它就实例化了,所以这种实例的创建方式是线程安全的。

public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton(); //to prevent creating another instance of Singleton
private Singleton(){} public static Singleton getSingleton(){
return INSTANCE;
}
}

你可以调用Singleton.getInstance()方法来获得实例对象。

2)枚举单例可以自己处理序列化

传统的单例模式的另外一个问题是一旦你实现了serializable接口,他们就不再是单例的了,因为readObject()方法总是返回一个 新的实例对象,就像java中的构造器一样。你可以使用readResolve()方法来避免这种情况,通过像下面的例子中这样用单例来替换新创建的实 例:

private Object readResolve(){
return INSTANCE;
}

如果你的单例类包含状态的话就变的更复杂了,你需要把他们置为transient状态,但是用枚举单例的话,序列化就不要考虑了。

3)枚举单例是线程安全的

就像第一点提到的,由于枚举实例的创建默认就是线程安全的,你不需要担心双检锁问题。

总结:通过提供序列化和线程安全并且几行代码搞定,说明枚举单例模式是java5之后创建单例最好的方法。你仍然可以使用其它你感觉很流行的方式来创建单例,但是我还是要找一个能够使我信服的观点让我不去使用枚举作为单例,如果你有,请告诉我!


推荐一个良心公众号【IT资源社】:

本公众号致力于免费分享全网最优秀的视频资源,学习资料,面试经验等,前端,PHP,JAVA,算法,Python,大数据等等,你想要的这都有

IT资源社-QQ交流群:625494093

也可添加微信拉你进微信群: super1319164238

微信搜索公众号:ITziyuanshe 或者扫描下方二维码直接关注,


作者:芥末无疆sss
链接:https://www.jianshu.com/p/7b3de9e0c983

为什么java中用枚举实现单例模式会更好的更多相关文章

  1. Java 利用枚举实现单例模式

    引言 单例模式比较常见的实现方法有懒汉模式,DCL模式公有静态成员等,从Java 1.5版本起,单元素枚举实现单例模式成为最佳的方法. Java枚举 基本用法 枚举的用法比较多,本文主要旨在介绍利用枚 ...

  2. Java枚举enum以及应用:枚举实现单例模式

    枚举作为一个常规的语言概念,一直到Java5才诞生不得不说有点奇怪,以至于到现在为止很多程序员仍然更喜欢用static final的形式去命名常量而不使用,一般情况下,Java程序员用这种方式去实现枚 ...

  3. 161208、Java enum 枚举还可以这么用

    在大部分编程语言中,枚举类型都会是一种常用而又必不可少的数据类型,Java中当然也不会例外.然而,Java中的Enum枚举类型却有着许多你意想不到的用法,下面让我们一起来看看. 先来看一段代码示例: ...

  4. Java设计模式学习记录-单例模式

    前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 ...

  5. Java常见设计模式之单例模式

         1.何为单例模式? 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的 ...

  6. Java与设计模式之单例模式(下) 安全的单例模式

          关于单例设计模式,<Java与设计模式之单例模式(上)六种实现方式>介绍了6种不同的单例模式,线程安全,本文介绍该如何保证单例模式最核心的作用——“实现该模式的类有且只有一个实 ...

  7. Java与设计模式之单例模式(上)六种实现方式

           阎宏博士在<JAVA与模式>中是这样描述单例模式的:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类.      ...

  8. Java enum枚举在实际项目中的常用方法

    在项目实际开发过程中,经常会遇到对某些固定的值.字典项的定义的需求,很多项目经常使用常量来定义,其实在jdk1.5就已经引入了枚举,使用枚举可以更好的解决这类需求,本文主要记录枚举的优势以及经常在项目 ...

  9. 《java常用设计模式之----单例模式》

    一.简介 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...

随机推荐

  1. Learn HTML5 in 5 Minutes!

    There's no question, HTML5 is a hot topic for developers. If you need a crash course to quickly unde ...

  2. 杭电oj-1002-A+B Problem

    Problem Description I have a very simple problem for you. Given two integers A and B, your job is to ...

  3. 怎么用secureCRT连接Linux

    首先要安装linux,参看:http://www.cnblogs.com/shenjieblog/p/5061282.html 然后要安装secureCRT,参看:http://www.cnblogs ...

  4. 设计模式——观察者模式(C++实现)

    #include <iostream> #include <vector> #include <algorithm> #include <iterator&g ...

  5. tcpdump抓包工具的使用

    个人原创,转载请注明,否则依法追究法律责任 2018-02-28  16:01:26 tcpdump 倾倒网络传输数据,直接启动tcpdump将监视第一个网络接口上所有流过的数据包. 1 不接任何参数 ...

  6. Java中instanceof关键字的用法

    Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. instanc ...

  7. Cxf 自动生成客户端服务端代码

    第一步: 下载apache-cxf安装包.并安装. 第二步: 配置cxf的环境变量. CXF_HOME = "CXF安装路径". 例如:F:\apache-cxf-2.1.2 在P ...

  8. selenium +python+windows 环境搭建

    很久不弄selenium了,好怀念,现在搭建下环境 1,先安装pip ,因为装的是python3,所以只要你不是在渣渣网站下载到坏的版本,在scripts目录下都有pip.exe文件 直接在环境变量里 ...

  9. Android类参考---SQLiteOpenHelper

    public 抽象类 SQLiteOpenHelper 继承关系 java.lang.Object |____android.database.sqlite.SQLiteOpenHelper 类概要 ...

  10. OC实现单选和多选按钮

    本代码库暂时有OC封装,改天有空在补一个Swift封装的,主要是因为swift不是那么熟,怕出错,半天找不到问题多尴尬呀! 先附上demo下载地址CSDN:http://download.csdn.n ...