head first 设计模式笔记5-单例模式
目录:
1、单例模式(Singleton Pattern)
2、概念
3、饿汉式:不是延迟加载,加载类的时候直接初始化
4、懒汉式:延迟加载,首次需要使用的时候在实例化,需要考虑线程安全
5、静态内部类实现
6、枚举实现
1、单例模式(Singleton Pattern) <==返回目录
确保一个类只有一个实例,并提供一个全局访问点。
2、概念 <==返回目录
下面的内容转载自博客: 23种设计模式之单例模式 ( https://chenmingyu.top/design-singleton/)
单例模式:单例模式属于创建型模式;
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。单例模式目的是保证在程序运行期间一个类只有一个实例,并提供一个全局访问点,无论什么情况下,只会生成一个实例,免去繁琐的创建销毁对象的过程。
优点:
)减少了内存开支,避免频繁地创建、销毁对象;
)避免对资源的多重占用;
缺点:
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化
如何设计单例模式
如何设计单例模式其实很简单,只需要考虑一个问题,实例是否可以保证是全局唯一。关于实例是否保证是全局唯一延伸出的问题:
是否线程安全,不安全肯定就不能保证全局只有一个实例
是否支持序列化,支持序列化的类,被反序列化之后肯定就不是全局唯一了
是否支持反射,支持反射肯定也不是全局唯一的
是否可以被克隆,这个也不能保证全局唯一
所以设计一个安全的单例需要考虑的问题还是很多的。针对上述问题常见的解决办法:
保证线程安全,使用volatile+synchronized实现
防止序列化攻击,重写readResolve方法
防止反射,常用的方案是在单例类里增加一个boolean类型的flag标识,在实例化的时候先判断flag标识
防止克隆,重写clone()方法
实现一个最简单的单例就需要考虑到以上的所有问题,这个时候什么有用的方法还没写那,代码就已经很多了,那有没有简单的办法既满足上述条件,代码又简洁那,那肯定有,使用枚举实现单例。
常见的单例模式实现
常见的单例模式实现方案大概有五种,懒汉模式,饿汉模式,双重检查方式实现,静态内部类实现,枚举实现
分个类:
是否支持延迟加载,分为懒汉模式和饿汉模式
线程安全设计了双重检查模式实现,静态内部类实现方式
不支持序列化,反射,克隆,枚举实现方式
其中懒汉模式,饿汉模式,双重检查方式实现,静态内部类的实现方式都可以概括为以下两步:
1.构造函数私有化,保证在外部无法new对象
2.提供一个static方法获取当前实例(不同方案,实现不同)
当然枚举的实现方式最简单,也最安全的,所以推荐使用枚举实现,其次推荐使用静态内部类方式实现。
3、饿汉式:不是延迟加载,加载类的时候直接初始化 <==返回目录
优点:线程安全,代码简单。
缺点:不是延迟加载,如果你用不到这个类,它也会实例化,还有一个问题就是如果这个实例依赖外部一些配置文件,参数什么的,在实例化之前就要获取到,否则就实例化异常
/**
* 单例模式:饿汉式
* @author oy
* @date 2019年9月3日 下午11:13:49
*/
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() {
} public static Singleton getInstance(){
return singleton;
}
}
4、懒汉式:延迟加载,首次需要使用的时候在实例化,需要考虑线程安全 <==返回目录
线程不安全的实现方式:
/**
* 单例模式:懒汉式,线程不安全
* @author oy
* @date 2019年9月3日 下午11:15:47*/
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance(){
if(null == singleton){
singleton = new Singleton();
}
return singleton;
}
}
线程安全的实现方式:双重检查(DCL:Double Check Lock)
/**
* 单例模式:双重检查(DCL:Double Check Lock)
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {} public static Singleton getInstance(){
if(null == singleton){
synchronized (Singleton.class){
if(null == singleton){
singleton = new Singleton();
}
}
}
return singleton;
}
}
面试题:为什么使用volatile修饰singleton变量?
1.说的volatile,首先肯定回答volatile的可见性
2.防止重排序优化,如果不用volatile修饰,多线程的情况下,可能会出现线程A进入synchronized代码块,
执行new Singleton();,首先给singleton分配内存,但是还没有初始化变量,
这时候线程B进入getInstance方法,进行第一个判断,此时singleton已经不为空,
直接返回singleton,然后肯定报错。使用volatile修饰之后禁止jvm重排序优化,所以就不会出现上面的问题
5、静态内部类实现 <==返回目录
使用静态内部类实现也是延迟加载,利用静态内部类去实现线程安全,只有在第一次调用getInstance方法的时候才会去加载SingletonHolder,初始化SINGLETON
/**
* 单例模式:静态内部类实现
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public class Singleton { private Singleton() {} public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
} private static class SingletonHolder {
private static final Singleton SINGLETON = new Singleton();
}
}
6、枚举实现 <==返回目录
枚举实现代码更简洁,线程安全,并且保证枚举不会被反序列化,反射和克隆
/**
* 单例模式:枚举实现
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public enum Singleton { SINGLETON; /**
* 提供的方法
*/
public void method() {
System.out.println("枚举实现");
}
}
head first 设计模式笔记5-单例模式的更多相关文章
- php设计模式笔记:单例模式
php设计模式笔记:单例模式 意图: 保证一个类仅有一个实例,并且提供一个全局访问点 单例模式有三个特点: 1.一个类只有一个实例2.它必须自行创建这个实例3.必须自行向整个系统提供这个实例 主要实现 ...
- Head First 设计模式笔记:单例模式
单例模式 确保一个类只有一个实例,并提供一个全局访问点. 类图: Singleton static uniqueInstance //其他属性... static getInstance() //其他 ...
- IOS设计模式浅析之单例模式(Singleton)
说在前面 进入正式的设计模式交流之前,扯点闲话.我们在项目开发的过程中,经常会不经意的使用一些常见的设计模式,如单例模式.工厂方法模式.观察者模式等,以前做.NET开发的时候,认真拜读了一下程杰老师的 ...
- 【白话设计模式四】单例模式(Singleton)
转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...
- Java设计模式之《单例模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...
- Java设计模式之【单例模式】
Java设计模式之[单例模式] 何为单例 在应用的生存周期中,一个类的实例有且仅有一个 当在一些业务中需要规定某个类的实例有且仅有一个时,就可以用单例模式 比如spring容器默认初始化的实例就是单例 ...
- Java设计模式中的单例模式
有时候在实际项目的开发中,我们会碰到这样一种情况,该类只允许存在一个实例化的对象,不允许存在一个以上的实例化对象,我们将这种情况称为Java设计模式中的单例模式.设计单例模式主要采用了Java的pri ...
- Java设计模式学习笔记(单例模式)
最近一直在看<Head First设计模式>,这本书写的确实是很不错的,专注于怎么用最简单的方式最通俗的语言让人了解设计模式.据说GoF的设计模式那本书写的很好,是一本经典,但是就是难懂, ...
- Java设计模式学习笔记(五) 单例模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 使用单例模式的原因 以Windows任务管理器为例,在Windows系统中,任务管理器是唯 ...
- PHP 设计模式 笔记与总结(6)基础设计模式:工厂模式、单例模式和注册树模式
三种基础设计模式(所有面向对象设计模式中最常见的三种): ① 工厂模式:使用工厂方法或者类生成对象,而不是在代码中直接new 在 Common 目录下新建 Factory.php: <?php ...
随机推荐
- Laravel策略(Policy)示例
场景:当前用户创建的订单,只能当前用户自己看,可以通过授权策略类(Policy)来实现 1.php artisan make:policy OrderPolicy 成功后,默认只有一个构造方法.因为涉 ...
- 走环概率问题(至今有点迷)--牛客第二场( Eddy Walker)
思路: 概率结论题,好像属于线性递推,现在也不太懂(lll¬ω¬) #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include < ...
- table表格的无缝循环
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 前端-CSS-初探-注释-语法结构-引入方式-选择器-选择器优先级-01(待完善)
目录 CSS(Cascading Style Sheet) CSS注释 CSS语法结构 CSS的三种引入方式 选择器 伪类.伪元素选择器速查 CSS选择器优先级***** 选择器相同的情况下 选择器不 ...
- Hive 教程(一)-安装与配置解析
安装就安装 ,不扯其他的 hive 依赖 在 hive 安装前必须具备如下条件 1. 一个可连接的关系型数据库,如 Mysql,postgresql 等,用于存储元数据 2. hadoop,并启动 h ...
- Codeforces 1201D. Treasure Hunting
传送门 看一眼感觉就是 $dp$,但是似乎状态太多了 考虑推推性质 首先每到一行都要把所有宝藏都走到,那么一定会走到最左边的和最右边的宝藏 注意到一旦走完所有宝藏时肯定是在最左边或者最右边的宝藏位置 ...
- LinkedList实现基于LRU算法的缓存
LinkedList实现基于LRU算法的缓存 2015年08月07日 18:18:45 秦江波 阅读数 2068 文章标签: java算法linkedlist缓存LRU更多 分类专栏: Java ...
- F12 开发人员工具中的控制台错误消息
使用此参考解释显示在 Internet Explorer 11 的控制台 和调试程序中的错误消息. 简介 使用 F12 开发人员工具进行调试时,错误消息(例如 EC7111 或 HTML1114)将显 ...
- 不基于比较的排序算法:Counting-sort和Radix-sort
- javascript原型与原型链个人理解
想了解原型和原型链,我觉得首先我们得知道javascript里有一个Object 与 Function,它俩都是构造函数,当然函数也是一个对象.我们打印Object 与 Function看一下, co ...