为什么java中用枚举实现单例模式会更好
代码简洁 这是迄今为止最大的优点,如果你曾经在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中用枚举实现单例模式会更好的更多相关文章
- Java 利用枚举实现单例模式
引言 单例模式比较常见的实现方法有懒汉模式,DCL模式公有静态成员等,从Java 1.5版本起,单元素枚举实现单例模式成为最佳的方法. Java枚举 基本用法 枚举的用法比较多,本文主要旨在介绍利用枚 ...
- Java枚举enum以及应用:枚举实现单例模式
枚举作为一个常规的语言概念,一直到Java5才诞生不得不说有点奇怪,以至于到现在为止很多程序员仍然更喜欢用static final的形式去命名常量而不使用,一般情况下,Java程序员用这种方式去实现枚 ...
- 161208、Java enum 枚举还可以这么用
在大部分编程语言中,枚举类型都会是一种常用而又必不可少的数据类型,Java中当然也不会例外.然而,Java中的Enum枚举类型却有着许多你意想不到的用法,下面让我们一起来看看. 先来看一段代码示例: ...
- Java设计模式学习记录-单例模式
前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 ...
- Java常见设计模式之单例模式
1.何为单例模式? 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的 ...
- Java与设计模式之单例模式(下) 安全的单例模式
关于单例设计模式,<Java与设计模式之单例模式(上)六种实现方式>介绍了6种不同的单例模式,线程安全,本文介绍该如何保证单例模式最核心的作用——“实现该模式的类有且只有一个实 ...
- Java与设计模式之单例模式(上)六种实现方式
阎宏博士在<JAVA与模式>中是这样描述单例模式的:作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. ...
- Java enum枚举在实际项目中的常用方法
在项目实际开发过程中,经常会遇到对某些固定的值.字典项的定义的需求,很多项目经常使用常量来定义,其实在jdk1.5就已经引入了枚举,使用枚举可以更好的解决这类需求,本文主要记录枚举的优势以及经常在项目 ...
- 《java常用设计模式之----单例模式》
一.简介 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创 ...
随机推荐
- MyBatis笔记03
1.动态sql 01.if:单独使用if,后面必须有where 1=1 代码:<!-- 需要注意的事项:01. 在xml文件中 特殊字符的使用 &&必须换成 and或者 & ...
- 开发IOS应用真的一定要买苹果电脑设备吗?
不要忘记目的 如果你想开发ios或者苹果的app,网上很多网友都会建议你买一个苹果硬件--苹果电脑,一部分建议你安装黑苹果.这两种方案中前一种费用很高,后一种费时费力(甚至到最后都要转向购买apple ...
- maven导入多模块项目
maven导入多模块项目 一.SVN上Maven多模块项目结构 使用eclipse导入SVN上的Maven多模块项目 Maven多模块项目所在SVN目录 二.eclipse通过SVN导入到工作空间 ...
- Java虚拟机系列-Java类加载机制
原文:http://www.ityouknow.com/jvm/2017/08/19/class-loading-principle.html 一. 类加载: 1. 将.class文件的二进制数据加载 ...
- Unity中List的随机排序(乱序)
为什么要给List排序做一个Unity限定条件呢 首先,是C#中的List泛型,若是Java,直接调用Collection.shuffle()就OK了 而Unity的C#版本较低,不能使用Random ...
- ServiceFabric极简文档-1.0 Service Fabric 自定义集群部署
Service Fabric 部署集群:https://docs.microsoft.com/zh-cn/azure/service-fabric/service-fabric-get-started ...
- .Net Core 2.0+ InfluxDB+Grafana+App Metrics 实现跨平台的实时性能监控
最近这段时间一直在忙,没时间写博客,负责了一个项目,从前端到后端一直忙,同时还有其他第几个项目的系统架构要处理. 去年就开始关注net core了,只是平时写写demo,没用在项目中,正好这次机会就用 ...
- mac安装tensorflow
tensorflow简介 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着基于数 ...
- 多进程浏览器、多线程页面渲染与js的单线程
线程与进程 说到单线程,就得从操作系统进程开始说起.在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单位.任务调度采用的是时间片轮转的抢占式调度方式,而进程 ...
- Java集合:TreeMap源码剖析
一.概念 TreeMap是基于红黑树结构实现的一种Map,要分析TreeMap的实现首先就要对红黑树有所了解. 要了解什么是红黑树,就要了解它的存在主要是为了解决什么问题,对比其他数据结构比如数组,链 ...