java23种设计模式之一: 单例模式(Singleton Pattern)
单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括:
1、理解什么是单例模式、单例模式有什么优点/缺点、单例模式的应用场景;
2、再来看看Java单例模式的6种代码实现方式、每种实现方式有什么需要注意的;
3、后面再来了解Java单例模式其他值得关注的地方,如比较静态方法、以及Java反射、反序列化、垃圾回收的影响等。
1、什么是单例模式
1-1、模式理解
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
UML结构图:

模式角色:
一个类使用了单例模式,称该类为单例类,如图中的Singleton。
单例模式三要点:
(1)、单例类只能有一个实例
这是最基本的,真正做到整个系统中唯一并不容易,通常还要考虑反射破坏、序列化/反序列化、对象垃圾回收等问题。
(2)、单例类必须自己创建自己的唯一实例
通常给实例构造函数protected或private权限。
(3)、单例类必须给所有其他对象提供这一实例
通常定义静态方法getInstance()返回。
1-2、特点
优点:
(1)、提供了对唯一实例的受控访问,避免对资源的多重占用。
(2)、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
(3)缩小名空间,避免全局变量污染空间,但比类操作更灵活。
缺点:
(1)、由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
(2)、 单例类的职责过重,在一定程度上违背了"单一职责原则"。
因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。 所以也不应过多使用单例模式。
1-3、应用
单例模式是一种对象创建型模式,用来编写一个类,在整个应用系统中只能有该类的一个实例对象。
常见应用场景:
线程池、缓存、日志、配置文件、打印机/显卡等硬件设备的驱动程序对象等等。
JDK中的一些应用:
java.lang.Runtime#getRuntime()
java.text.NumberFormat#getInstance()
java.awt.GraphicsEnvironment#getLocalGraphicsEnvironment()
2、单例模式实现示例
2-1、饿汉式(简单可用)
Lazy 初始化:否;
多线程安全:是;
描述:
这种方式比较常用,它基于JVM的类加载器机制避免了多线程的同步问题,对象在类装载时就实例化,所以称为饿汉式。
优点:没有加锁,执行效率会提高。
缺点:没有Lazy初始化,可能有时候不需要使用,浪费内存。
代码实例:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
2-2、懒汉式(线程不安全,不可用)
Lazy 初始化:是;
多线程安全:否;
描述:
能够在getInstance()时再创建对象,所以称为懒汉式。这种实现最大的问题就是不支持多线程。因为没有加锁同步。
代码实例:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
2-3、同步方法的懒汉式(同步方法效率低,不推荐)
Lazy 初始化:是
多线程安全:是
描述:
除第一次使用,后面getInstance()不需要同步;每次同步,效率很低。
代码实例:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
2-4、双重校验锁(可用)
Lazy 初始化:是;
多线程安全:是;
描述:
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
实例变量需要加volatile 关键字保证易变可见性,JDK1.5起才可用。
代码实例:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
2-5、静态内部类(推荐)
Lazy 初始化:是;
多线程安全:是;
描述:
同样利用了JVM类加载机制来保证初始化实例对象时只有一个线程,静态内部类SingletonHolder 类只有第一次调用 getInstance 方法时,才会装载从而实例化对象。
代码实例:
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
2-6、枚举(《Effective Java》推荐,不常见)
Lazy 初始化:否;
多线程安全:是;
描述:
从Java1.5开始支持enum特性;无偿提供序列化机制,绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候。
不过,用这种方式写不免让人感觉生疏,这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。
代码实例
public enum Singleton {
//定义一个枚举的元素,就代表Singleton实例
INSTANCE;
/*
**假如还定义有下面的方法,调用:Singleton.INSTANCE.doSomethingMethod();
*/
public void doSomethingMethod() {
}
2-7、小结
以上6种单例实现方式,不是线程安全的不能用,至于是否需要延时加载,看情况而定。
一般情况下,使用最基本、最简单的第一种饿汉式就行了(JDK中有不少使用该种方式),需要延时加载的使用静态内部类方式,需要高安全性的可以使用第6种枚举方式。
java23种设计模式之一: 单例模式(Singleton Pattern)的更多相关文章
- 二十四种设计模式:单例模式(Singleton Pattern)
单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...
- 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...
- 设计模式之单例模式(Singleton Pattern)
单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...
- 【设计模式】单例模式 Singleton Pattern
通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance) 的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...
- Java23种设计模式之单例模式
一.单例模式简介 单例模式是Java设计模式中常见的一种模式.主要分为懒汉式单例.饿汉式单例.登记式单例: 单例模式的特点: 1.单例类只能有一个实例: 2.单例类必须自己创建自己的唯一的实例: ...
- 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)【转】
介绍 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例 保证一个类仅有一个实例. Singleton using System; using System.Collections.Gene ...
- Java 设计模式(三)-单例模式(Singleton Pattern)
1 概念定义 1.1 定义 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 1.2 类型 创建类模式 1.3 难点 1)多个虚拟机 当系统中的单例类被拷贝运行在多 ...
- python 设计模式之单例模式 Singleton Pattern
#引入 一个类被设计出来,就意味着它具有某种行为(方法),属性(成员变量).一般情况下,当我们想使用这个类时,会使用new 关键字,这时候jvm会帮我们构造一个该类的实例.这么做会比较耗费资源. 如果 ...
- 【UE4 设计模式】单例模式 Singleton Pattern
概述 描述 保证一个类只有一个实例 提供一个访问该实例的全局节点,可以视为一个全局变量 仅在首次请求单例对象时对其进行初始化. 套路 将默认构造函数设为私有, 防止其他对象使用单例类的 new运算符. ...
随机推荐
- windows+python3.6下安装fasttext+fasttext在win上的使用+gensim(fasttext)
真是坑了好久,faxttext对win并不是很友好,所以遇到了很多坑,记录下来,以供大家少走弯路. 法1:刚开始直接用pip install fasttext,最后一直报下面这个错误 “error:M ...
- Coursera在线学习---第五节.Logistic Regression
一.假设函数与决策边界 二.求解代价函数 这样推导后最后发现,逻辑回归参数更新公式跟线性回归参数更新方式一摸一样. 为什么线性回归采用最小二乘法作为求解代价函数,而逻辑回归却用极大似然估计求解? 解答 ...
- 宋牧春: Linux设备树文件结构与解析深度分析(2) 【转】
转自:https://mp.weixin.qq.com/s/WPZSElF3OQPMGqdoldm07A 作者简介 宋牧春,linux内核爱好者,喜欢阅读各种开源代码(uboot.linux.ucos ...
- c++动态规划dp算法题
问题1:找硬币,换钱的方法 输入: penny数组代表所有货币的面值,正数不重复 aim小于等于1000,代表要找的钱 输出:换钱的方法总数 解法1:经典dp,空间复杂度O(n*aim) class ...
- ../include/squid_md5.h:27:2: error: #error Cannot find OpenSSL MD5 headers【squid安装中】
../include/squid_md5.h:27:2: error: #error Cannot find OpenSSL MD5 headers yum install -y openssl* w ...
- c++鼠标点点,获取坐标值,放入到txt文件中
// oj3.cpp : Defines the entry point for the console application.// #include "stdafx.h"#in ...
- 4、GitLab 创建、删除、修改项目
一.gitLab创建项目 1.创建用户组 2.填写组信息后单击“Create group” 其中:“Group path”将显示在git路径中 3.选择需要加入该组的“用户”和“角色”后点击“Add ...
- 【前端笔记】浅谈js继承
我们先想想我们用js最后要怎样实现面向对象的编程.事实上我们必须用上原型链这种东西. 我们的父类superType有属性和方法,并且一些能被子类subType继承,一些能被覆盖,但是丝毫不会影响到父类 ...
- WordPress插件:自定义登录注册插件:DX Login Register
众所周知,wordpress自带的注册系统比较简单,需要接收邮件密码才能完成.不过对于国内的站长来说,会碰到不少麻烦.首先个人站长一般都使用虚拟主机,有不少还是使用国外的,你的服务器不一定会提供邮件发 ...
- [实战]MVC5+EF6+MySql企业网盘实战(5)——登录界面,头像等比例压缩
写在前面 关于该项目,已经很久没更新了.实在是找不到一个好的ui,没办法就在网上找了一个还不错的,就凑合着先用着吧,先出第一版,以后的再想着去优化.最近更新与网盘项目相关的内容是准备在项目中使用一个美 ...