设计模式:单例(Sigleton)模式
题目:设计一个类,我们只能生成该类的一个实例。 只能生成一个实例的类是实现了Singleton(单例)模式的类型。
相关知识:
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
介绍
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
应用实例:
- 1、一个班级只有一个班主任。
- 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
- 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
使用场景:
- 1、要求生产唯一序列号。
- 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
创建步骤:
1、创建一个单例类Singleton
2、让构造函数为私有private,这样该类就不会被实列化
3、提供一个static方法获取其唯一可用的对象。
实现1:懒汉式,线程不安全
/*
* 1、懒汉式,线程不安全
* 是否 Lazy 初始化:是
* 是否多线程安全:否
* 实现难度:易
* 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
* 这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
**/
public class Singleton1 {
private static Singleton1 instance; private Singleton1(){} //让构造函数为 private,这样该类就不会被实例化 //获取唯一可用的对象
public static Singleton1 getInstance(){
if(instance == null){
instance = new Singleton1(); //创建 Singleton 的一个对象
}
return instance;
}
}
实现2:懒汉式,线程安全
/*
* 2、懒汉式,线程安全
* 是否 Lazy 初始化:是
* 是否多线程安全:是
* 实现难度:易
* 描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
* 优点:第一次调用才初始化,避免内存浪费。
* 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
* getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。
* */
public class Singleton2 {
private static Singleton2 instance;
private Singleton2(){} public static synchronized Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
}
实现3:饿汉式
/*
* 3、饿汉式
* 是否 Lazy 初始化:否
* 是否多线程安全:是
* 实现难度:易
* 描述:这种方式比较常用,但容易产生垃圾对象。
* 优点:没有加锁,执行效率会提高。
* 缺点:类加载时就初始化,浪费内存。
* 它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,
* 虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法,
* 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
* */
public class Singleton3 {
private static Singleton3 instance = new Singleton3();
private Singleton3(){} public static Singleton3 getInstance(){
return instance;
}
}
实现4:双检锁/双重校验锁
/*
* 4、双检锁/双重校验锁(DCL,即 double-checked locking)
* JDK 版本:JDK1.5 起
* 是否 Lazy 初始化:是
* 是否多线程安全:是
* 实现难度:较复杂
* 描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
* getInstance() 的性能对应用程序很关键。
* */
public class Singleton4 {
private volatile static Singleton4 singleton;
private Singleton4(){} public static Singleton4 getSingleton(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton4();
}
}
}
return singleton;
}
}
实现5:登记式/静态内部类
/*
* 5、登记式/静态内部类
* 是否 Lazy 初始化:是
* 是否多线程安全:是
* 实现难度:一般
* 描述:这种方式能达到双检锁方式一样的功效,但实现更简单。
* 对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。
* 这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
* 这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟第 3 种方式不同的是:
* 第 3 种方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),
* 而这种方式是 Singleton 类被装载了,instance 不一定被初始化。
* 因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。
* 想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,
* 因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合理。
* */
public class Singleton5 {
private static class SingletonHolder{
private static final Singleton5 INSTANCE = new Singleton5();
}
private Singleton5(){} public static final Singleton5 getInstance(){
return SingletonHolder.INSTANCE;
}
}
实现6:枚举
/*
* 6、枚举
* JDK 版本:JDK1.5 起
* 是否 Lazy 初始化:否
* 是否多线程安全:是
* 实现难度:易
* 描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。
* 它更简洁,自动支持序列化机制,绝对防止多次实例化。
* 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,
* 而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
* 不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
* 不能通过 reflection attack 来调用私有构造方法。
* */
public enum Singleton6 {
INSTANCE;
public void whateverMethod(){ }
}
经验之谈:一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。
应用
在JDK中,java.lang.Runtime就是经典的单例模式(饿汉式)
参考与推荐:
1、http://www.blogjava.net/kenzhh/archive/2016/03/28/357824.html
设计模式:单例(Sigleton)模式的更多相关文章
- Android与设计模式——单例(Singleton)模式
概念: java中单例模式是一种常见的设计模式.单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类仅仅能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...
- JavaScript 设计模式之----单体(单例)模式
设计模式之--单体(单例)模式 1.介绍 从本章开始,我们会逐步介绍在JavaScript里使用的各种设计模式实现,在这里我不会过多地介绍模式本身的理论,而只会关注实现.OK,正式开始. 在传统开发工 ...
- 漫谈设计模式(二):单例(Singleton)模式
1.前言 实际业务中,大多业务类只需要一个对象就能完成所有工作,另外再创建其他对象就显得浪费内存空间了,例如web开发中的servlet,这时便要用到单例模式,就如其名一样,此模式使某个类只能生成唯一 ...
- 《连载 | 物联网框架ServerSuperIO教程》- 8.单例通讯模式开发及注意事项
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- 单例/单体模式(Singleton)
单例/单体模式(Singleton) 首先,单例模式是对象的创建模式之一,此外还包括工厂模式. 单例模式的三个特点: 1,该类只有一个实例 2,该类自行创建该实例(在该类内部创建自身的实例对象) 3, ...
- java设计模式——单例(Singleton)模式
在某些场景,你需要找到一个承担职责的对象,并且这个对象是他所属类的唯一实例.此时可以使用单例模式. 单例模式的意图是为了确保一个类有且仅有一个实例,并为他提供一个全局的访问点.创建一个担当独一无二角色 ...
- 设计模式C++描述----01.单例(Singleton)模式
一.概念 单例模式:其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享. class CSingleton { //公有的静态方法,来获取该实例 public: s ...
- 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)
回到目录 之前的讲过两篇关于日志组件的文章,分别是<第一回 日志记录组件之自主的Vlog>和<第三回 日志记录组件之log4net>,而今天主要说一下我自己开发的另一种日志 ...
- javascript学习(9)——[设计模式]单例
单例模式,相信大家对此都不陌生,我们主要讲下javascript中几个比较常见的设计模式: (1).普通的单体 (2).具有局部变量的强大单体 (3).惰性单体 (4).分支单体 下面我们就一一进行介 ...
随机推荐
- Shell编程 | 脚本参数与交互及常见问题
在执行一个脚本程序时,会经常需要向脚本传递一些参数,并根据输入的参数值生成相应的数据或执行特定的逻辑. 向脚本传递参数 执行Shell脚本时可以带有参数,在Shell脚本中有变量与之对应进行引用.这类 ...
- 2019.6.11_MySQL进阶三:临时表
临时表 临时表主要应用于保存一些临时数据.临时表只在当前连接可见.当关闭连接时,MySQL会自动删除表并且释放空间.临时表在MySQL 3.23版本中添加,低于 3.23版本就无法使用MySQL的临时 ...
- selenium 简介 及浏览器配置
简介: Selenium是一款基于web应用程序的开源测试工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.Selenium是一个自动化的web应用功能测试工具. Seleniu ...
- Mysql对表中 数据 的操作 DML
上一知识点回顾: mysql的备份: 直接使用navicat进行备份 转储SQL文件:有结构和数据/ 仅结构 两种 需要还原时 单击 数据库名字 运行SQL文件 创建表ctreate 修改表alt ...
- Spring事务异常rollback-only 笔记
造成以上异常的原因情形: 在spring里面我们配置了事务的传播机制是REQUIRED,所以这两个事务最终会合并成一个事务.当a方法调用b方法时,程序中a方法中由于某某原因导致抛出异常(或者明确将该事 ...
- 学习input
认识input: 在网页中,我们经常都会遇到一些交互页面,比如登录.注册.评论等页面.你知道在html中用的是那些标签吗?今天我们要学习的就是其中最主要的一个标签,即<input>标签. ...
- 第09组 Beta冲刺(1/5)
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 任务分配 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任 ...
- gulp的初阶使用方法(转)
安装好gulp之后接下来就是使用了,此文主要介绍一些前端开发时常用的一些插件及其用法 http://www.imooc.com/article/tag/26/hot/12插件安装 安装本地服务器插件: ...
- ShellScript之变量
Shell脚本之变量学习 ##########################ShellScript初学者,文章摘自菜鸟教程################################ 1.She ...
- 2018 ACM-ICPC徐州站网络赛 G题
There's a beach in the first quadrant. And from time to time, there are sea waves. A wave ( xxx , yy ...