Java设计模式探讨之单例模式
单例模式是在平时的项目开发中比较常见的一种设计模式,使用比较普遍,网上的资料也是一抓一大把,小Alan也来凑凑热闹,为以后充实点设计模式相关的内容做个简单的开篇。
单例模式是一种创建对象的模式,用于产生这个类的一个具体的实例对象,跟普通的对象创建比起来就那么一点点区别,区别就在于它可以确保项目中的一个类只会产生一个具体的对象实例。而不会出现第二个对象实例,第三个对象实例。所有使用到这个对象实例的地方实际上用的都是同一个对象,这就是所谓的单例模式,对于初学者还可能陌生,对于老司机们来讲这可是最最简单的设计模式之一。
在Java中使用单例模式有哪些好处嘞?
①对于频繁使用、经常使用的对象,可以省略创建对象也就是没对象的需要new一个对象所花费的时间,这对于那些重量级的对象来说,还是能少来一个就少来一个,用老对象就好了,减少开销;
②创建对象的次数变少了,对系统内存使用的频率就会降低,这样就减轻了GC的压力,缩短了GC所耗费的时间;
③开发项目的过程中遇到类只需要一个对象实例的时候,那么就是选择这模式无疑了。
单例的实现1:
下面给出一个单例的实现,这个实现是so easy的,代码如下:
/** * 单例模式 * @author AlanLee * */ public class Singleton { // 饿汉模式 private static Singleton instance = new Singleton(); private Singleton() { System.out.println("Singleton is create"); } public static Singleton getInstance() { return instance; } }
使用这种方式创建单例对象有几点需要特别注意。
第一点:我们要保证我们的项目中不会有人意外的创建多余的对象实例的话,我们需要把Singleton的构造函数设置为private私有的。这样其他开发人员就不能随便的创建这个类的对象实例了,从而避免该类的对象实例被错误的创建出来;
第二点:instance对象必须是private私有的并且static静态化的。如果不是private私有的,那么instance的安全性无法得到保证。一不小心可能就被其他开发人员来个Singleton.instance=xxx的,那这个对象也就被改变了,如果=null的话,可想而知,在使用这个对象实例的使用,迎接你的将是空对象异常的怀抱。其次,因为工厂方法getInstance()是static静态方法,因此方法中返回的变量也得是static的。
探讨:每种实现方式在高并发环境下性能如何呢,每种实现方式有木有什么不足之处?
这个单例模式的实现方式性能是非常好的,因为工厂方法getInstance()只是简单的返回instance对象实例,并没有任何锁操作,因此在并行程序中,还是会有比较不错的表现滴。
但是这种方式有一点不足,就是instance对象实例在什么时候被创建出来是不受控制的,基础好点的都知道static成员会在类第一次初始化的时候被创建,这个时候可不一定是工厂方法getInstance()第一次被调用的时候。
假设你的单例模式是这样的,代码如下:
/** * 单例模式:实例对象第一次初始化的问题 * * @author AlanLee * */ public class Singleton2 { public static int STATUS = 1; private static Singleton2 instance = new Singleton2(); private Singleton2() { System.out.println("Singleton2 is create"); } public static Singleton2 getInstance() { return instance; } }
注意,这个单例还包含另一个静态成员STATUS。此时,在任何地方引用这个STATUS都会导致instance对象实例被创建(任何对Singleton2方法或者字段的引用,都会导致类初始化,并创建instance实例,但是类初始化只有一次,因此instance实例永远只会被创建一次)。
比如:System.out.println(Singleton.STATUS);
上述println会打印出:
可以看到,就算我们没有要求创建instance单例对象,new Singleton2()也会被调用。
如果不在乎这个小小的不足之处,这种单例模式的实现方式是一种不错的选择。它容易实现,代码易读而且性能优越。
单例的实现2:
如果你想精准的控制instance的创建时间,那么就需要使用下面这种方式,一种支持延迟加载的策略,它只会在instance被第一次使用时才会创建对象。代码如下:
/** * 单例模式之懒汉模式 * * @author AlanLee * */ public class LazySingleton { private static LazySingleton instance = null; private LazySingleton() { System.out.println("LazySingleton is create"); } public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
最初我们并不需要实例化instance对象实例,只有工厂方法getInstance()被第一次调用时才会创建单例对象。但是在高并发环境下,为了防止对象被对此创建,我们不得不使用synchronized进行方法同步。这种实现的好处是,充分利用了延迟加载,只有在真正需要时才创建对象。但坏处也很明显,并发环境下加锁,在锁竞争激烈的时候会对性能产生一定的影响。
此外,还有一种被称为双重检查模式的方法可以用于创建单例。这是一种非常丑陋、复杂的方法,甚至在低版本的JDK中都不能保证正确性。不推荐使用,也没必要在这种方法上花费太多时间。
单例的实现3:
在上述的单例模式实现方式中,可说是各有千秋,那么第三种方式便是结合两者的优势的一种两全其美的实现方式,代码如下:
/** * 无懈可击之单例模式 * * @author Alanlee * */ public class StaticSingleton { private StaticSingleton() { System.out.println("StaticSingleton is create"); } private static class SingletonHolder { private static StaticSingleton instance = new StaticSingleton(); } public static StaticSingleton getInstance() { return SingletonHolder.instance; } }
上述代码实现了一个单例模式,并且同时拥有前两种方式的优点。首先工厂方法getInstance()没有使用同步锁,这使得在高并发环境下性能得到了提升。其次,只有在工厂方法getInstance()被第一次调用时,StaticSingleton的实例才会被创建。这种方式巧妙地使用了内部类和类的初始化方式。内部类SingletonHolder被申明为private私有的,这使得我们不可能在外部访问并初始化它。而我们只能在工厂方法getInstance()内部对SingletonHolder类进行初始化,利用虚拟机的类初始化机制创建单例对象。
结束语:宠辱不惊,闲看庭前花开花落;去留无意,漫随天外云卷云舒......小Alan除了喜欢看技术书籍,还是一个武侠玄幻小说爱好者呢!希望自己在IT的这条道路上就能像小说中的主人公一样,纵然困难重重,亦能化险为夷成就康庄大道,至于坐拥美女环抱啥的,小Alan可不想啊,还是有一个深爱的女人足以。
可爱博主:AlanLee
博客地址:http://www.cnblogs.com/AlanLee
本文出自博客园,欢迎大家加入博客园。
Java设计模式探讨之单例模式的更多相关文章
- Java设计模式之《单例模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...
- Java设计模式之【单例模式】
Java设计模式之[单例模式] 何为单例 在应用的生存周期中,一个类的实例有且仅有一个 当在一些业务中需要规定某个类的实例有且仅有一个时,就可以用单例模式 比如spring容器默认初始化的实例就是单例 ...
- Java设计模式中的单例模式
有时候在实际项目的开发中,我们会碰到这样一种情况,该类只允许存在一个实例化的对象,不允许存在一个以上的实例化对象,我们将这种情况称为Java设计模式中的单例模式.设计单例模式主要采用了Java的pri ...
- 重学 Java 设计模式:实战单例模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 5个创建型模式的最后一个 在设计模式中按照不同的处理方式共包含三大类:创建型模式.结 ...
- Java设计模式4:单例模式
前言 非常重要,单例模式是各个Java项目中必不可少的一种设计模式.本文的关注点将重点放在单例模式的写法以及每种写法的线程安全性上.所谓"线程安全性"的意思就是保证在创建单例对象的 ...
- 10.Java设计模式 工厂模式,单例模式
Java 之工厂方法和抽象工厂模式 1. 概念 工厂方法:一抽象产品类派生出多个具体产品类:一抽象工厂类派生出多个具体工厂类:每个具体工厂类只能创建一个具体产品类的实例. 即定义一个创建对象的接口(即 ...
- Java设计模式学习01——单例模式(转)
原地址:http://blog.csdn.net/xu__cg/article/details/70182988 Java单例模式是一种常见且较为简单的设计模式.单例模式,顾名思义一个类仅能有一个实例 ...
- 【java设计模式】-04单例模式
单例模式 定义: 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 类型: 创建类模式 类图: 单例模式特点 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单 ...
- Java设计模式09:单例模式的强化(控制实例个数n)
1. 单例模式的本质: 控制实例数目(目的节约资源) 2. 单例模式体现的一些思想: (1)延迟装载(Lazy Load):懒汉式 (2)缓存:饿汉式 3. 单例模式的变形使用: 控制使用实例个数为3 ...
随机推荐
- Tiled Editor 图块的两种导入方式
一.图块集图块的导入. 打开或者创建地图后,新建 新图块. 弹出新图块面板 图块类型选择 "基于图块集图块",一定要选择"嵌入地图",否则需要另存为其他类型的文 ...
- 字符、字符集、编码,以及它们python中会遇到的一些问题(下)
在看了很多的博客文章之后,总结整理得到了以下文章,非常感谢这些无私奉献的博主! 文章末尾有本文引用的文章的链接,如果有漏掉的文章引用,可以发邮件联系我,随后再次附上链接! 侵删!!! 这一部分是下篇, ...
- java实现excel和数据的交互
1. 环境要求 本文环境为: 数据库为oracle,jdk为jdk7,依赖jar包为ojdbc6-11.2.0.4.0.jar+poi-3.14.jar 2.POI 使用 1. 建立工作空间 2. 获 ...
- 基于c编写的关于随机生成四则运算的小程序
基于http://www.cnblogs.com/HAOZHE/p/5276763.html改编写的关于随机生成四则运算的小程序 github源码和工程文件地址:https://github.com/ ...
- java 线程二
一.线程的优先级别 线程优先级别的使用范例: 1 package cn.galc.test; 2 3 public class TestThread6 { 4 public static void m ...
- C#操作SqlServer MySql Oracle通用帮助类Db_Helper_DG(默认支持数据库读写分离、查询结果实体映射ORM)
[前言] 作为一款成熟的面向对象高级编程语言,C#在ADO.Net的支持上已然是做的很成熟,我们可以方便地调用ADO.Net操作各类关系型数据库,在使用了多年的Sql_Helper_DG后,由于项目需 ...
- 大数据 - Teradata学习体会
引言 随着计算机系统在处理能力.存储能力等方面,特别是计算机软件技术的不断提高,使得信息处理技术得到飞速发展. 数据处理主要分为两大类:联机事物处理OLTP.联机分析处理OLAP.OLTP也就是传统的 ...
- QT的安装及环境配置
QT的安装及环境配置 一.windows的下QT的安装及环境配置 (一)从框架安装程序中安装 步骤: 准备:下载QT库,下载指定版本的MINGW,QT IDE 1.下载QT安装文件如:qt-win-o ...
- JSP入门 Listener
实现HttpSessionListener 编写一个OnlineUserListener类 package anni; import java.util.List; import javax.serv ...
- Even Parity uva11464 模拟
Even Parity Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu [Submit] ...