设计模式01 创建型模式 - 单例模式(Singleton Pattern)
参考
单例模式(Singleton Pattern)
确保一个类有且仅有一个实例,并且为客户提供一个全局访问点。
特点
1) 保证被访问资源对象在内存中只有一个实例,节约了系统内存资源,也避免了对资源多重占用;
2) 封装了访问实例方法,提供全局访问点,严格控制客户的访问方式;
3) 通常常驻内存,不会频繁创建/销毁,节约了系统开销;
缺点
1) 没有抽象层,难以扩展;
2) 类的职责过重,往往一个单例负责所有与之相关功能,违背了类设计的“职责单一”原则;
3) 单例如果持有context,容易造成内存泄漏;
4) 全局共享一个实例资源,难以隔离问题,进行单独测试;
适用场景
1)全局随时可能需要访问,访问方式复杂,而且资源受限;
2)需要常驻内存,避免频繁创建、销毁的资源;
demo
单例模式通用UML类图
单例模式的8种写法与多线程
单例模式为了不让外部随意构建实例,一般需要将构造函数声明为private,在获取实例对象时,就无法通过动态函数来读取(因为此时实例还未初始化),故只能通过类方法(static方法)来获取实例引用。
1. 饿汉式 静态常量 立即加载
// Singleton.java
// 饿汉式 静态常量
public class Singleton {
private final static Singleton INSTANCE = new Singleton(); private Singleton() { }
public static Singleton getInstance() { return INSTANCE; } public void displaySingleton(){
System.out.println("单例初始化方式: 饿汉式 静态常量");
}
}
特点:简单,类装载时完成初始化,不存在多线程同步问题;
优点:没有延迟实例化,如果程序一直没有使用,会造成资源浪费;
2.饿汉式 静态代码块 立即加载
与饿汉式 静态常量类似,只是把实例初始化放在了类的静态代码块中,而非放在实例引用定义处。
// Singleton1.java
// 饿汉式 静态代码块
public class Singleton1 {
private static Singleton1 instance; static{
instance = new Singleton1();
} private Singleton1(){} public static Singleton1 getInstance(){
return instance;
} public void displaySingleton(){
System.out.println("单例初始化方式: 饿汉式 静态代码块");
}
}
3. 懒汉式 延迟加载 线程不安全
如果在执行多个线程同时执行到instance == null,就会造成多次实例化。只适合单线程情况使用。
// Singleton2.java
// 懒汉式 延迟实例化 线程不安全
public class Singleton2 {
private static Singleton2 instance; private Singleton2(){} public static Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
}
4.懒汉式 延迟加载 线程安全(同步方法)
效率低下,每次线程通过getInstance获取实例,甚至在对象已经实例化后,都要先等待别的线程释放资源。
// Singleton3.java
// 懒汉式 延迟实例化 线程安全(同步方法)
public class Singleton3 {
private static Singleton3 instance; private Singleton3(){} public static synchronized Singleton3 getInstance(){
if(instance == null){
instance = new Singleton3();
}
return instance;
} public void displaySingleton(){
System.out.println("Singleton3单例初始化方式: 懒汉式 延迟实例化 线程安全(同步方法)");
}
}
5. 懒汉式 延迟实例化 线程安全(同步代码块)
效率比4(同步方法)高,但是多线程可能会出现多次实例化的问题。
//Singleton4.java
//懒汉式 延迟实例化 线程安全(同步代码块)
public class Singleton4 {
private static Singleton4 instance;
private Singleton4(){} public static Singleton4 getInstance(){
if(instance == null) {
synchronized (Singleton4.class) {
instance = new Singleton4();
}
} return instance;
} public void displaySingleton(){
System.out.println("Singleton4单例初始化方式: 懒汉式 延迟实例化 线程安全(同步代码块)");
}
}
6. 懒汉式 线程安全(双重检查)
综合了4,5即线程安全(同步方法)和线程安全(同步代码块)的优缺点,解决了4的低效问题,又解决了5的多次实例化不安全问题。
// Singleton5.java
// 懒汉式 线程安全(双重检查)
public class Singleton5 {
private static Singleton5 instance; private Singleton5(){} public static Singleton5 getInstance(){
if(instance == null){
synchronized(Singleton5.class){
if(instance == null) {
instance = new Singleton5();
}
}
}
return instance;
} public void displaySingleton(){
System.out.println("Singleton5单例初始化方式: 懒汉式 线程安全(双重检查)");
}
}
7. 静态内部类
与饿汉式类似,都是通过类的装载机制来初始化实例,不过,既解决了饿汉式无法延迟实例化的问题,又解决了线程安全的问题。
// Singleton6.java
// 静态内部类
public class Singleton6 {
private Singleton6(){} private static class SingletonInstance{
private static final Singleton6 INSTANCE = new Singleton6();
} public static Singleton6 getInstance(){
return SingletonInstance.INSTANCE;
} public void displaySingleton(){
System.out.println("Singleton6单例初始化方式: 静态内部类 线程安全");
}
}
8. 枚举类型
通过枚举类型在构造的时候,被实例化。不仅能解决多线程问题,还能防止反序列化创建新的对象。JDK1.5之后才加入,现使用较少。
// Singleton7.java
// 枚举类型
public enum Singleton7 {
INSTANCE;
public void display(){
System.out.println("Singleton7单例初始化方式: 枚举类型");
}
}
总结
1. 实现单例模式的核心在与私有化构造方法,在getInstance方法中读取实例引用。
2. 如果是类加载时,就实例化,就成为饿汉式;否则,在getInstance方法中才实例化称为懒汉式。
3. 各种实现方法比较
实现方法 | 特点 | 是否线程安全 | 是否推荐 |
饿汉式,静态常量 | 立即加载 | 是 | 可以用 |
饿汉式,静态代码块 | 立即加载 | 是 | 可以用 |
一般懒汉式 | 延迟加载 | 否 | 多线程不可用 |
懒汉式,同步方法 | 延迟加载,效率低 | 是 | 可以用,不推荐 |
懒汉式,同步代码块 | 延迟加载,多次实例化 | 否 | 不可用 |
懒汉式,双重验证 | 延迟加载,效率高 | 是 | 推荐 |
静态内部类 | 延迟加载,效率高 | 是 | 推荐 |
枚举类型 | 延迟加载,效率高,应用较少(>JDK1.5) | 是 | 推荐 |
设计模式01 创建型模式 - 单例模式(Singleton Pattern)的更多相关文章
- "围观"设计模式(7)--创建型之单例模式(Singleton Pattern)
单例模式,也叫单子模式,是一种经常使用的软件设计模式.在应用这个模式时,单例对象的类必须保证仅仅有一个实例存在. 很多时候整个系统仅仅须要拥有一个的全局对象.这样有利于我们协调系统总体的行为.比方在某 ...
- 设计模式01 创建型模式 - 原型模式(Protype Pattern)
参考 1. 设计模式:原型模式 | 博客园 2. Java clone深拷贝.浅拷贝 | CSDN 3. Cloneable接口和Object的clone()方法 | 博客园 原型模式(Prototy ...
- 设计模式01 创建型模式 - 建造者模式(Build Pattern)
参考 1. Builder Design Pattern | Youtube 2. 建造者模式(Builder和Director)| 博客园 3. 深入理解Builder模式 | 简书 建造者模式(B ...
- Java设计模式之创建型模式
创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类
- [19/04/22-星期一] GOF23_创建型模式(单例模式)
一.概念 <Design Patterns: Elements of Reusable Object-Oriented Software>(即后述<设计模式>一书),由 Eri ...
- GoF的23种设计模式之创建型模式的特点和分类
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”.这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成.就像我们去商场购买商品时, ...
- Typescript玩转设计模式 之 创建型模式
作者简介 joey 蚂蚁金服·数据体验技术团队 前言 我们团队的工作是用单页面应用的方式实现web工具.涉及到数万到十数万行的前端代码的管理,而且项目周期长达数年. 怎么样很好地管理好这种量级的前端代 ...
- Python版设计模式: 创建型模式:单例模式和工厂模式家族
一. 单例模式(Singleton) 所谓单例模式,也就是说不管什么时候都要确保只有一个对象实例存在.很多情况下,整个系统中只需要存在一个对象,所有的信息都从这个对象获取,比如系统的配置对象,或者是线 ...
- Python与设计模式之创建型模式及实战
用Python学习一下设计模式,如果很枯燥的话,就强行能使用的就用一下.设计模式参考Python与设计模式-途索 1. 单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点. import ...
随机推荐
- 2.6 XML配置:XML文件节点说明
来源:http://blog.csdn.net/five3/article/details/25907693 TestNG的DTD检查文件:http://testng.org/testng-1.0.d ...
- [NLP]Transformer模型解析
简介[2] Attention Is All You Need是2017年google提出来的一篇论文,论文里提出了一个新的模型,叫Transformer,这个结构广泛应用于NLP各大领域,是目前比较 ...
- redis集群(Sentinel)
问题 Redis 主哨兵模式是如何保证高可用的 主要依赖主哨兵的发现故障和故障转移 概述 本文假设读者对redis 的主从复制已经进行了了解 . Redis 主哨兵集群为Redis 提供了高可用,即高 ...
- Layui自定义模块的使用方式
为什么要自定义模块呢?好处很多.比如可以大量重用代码...... 根据layui官方的文档说明.首先第一步是要确定你要扩展的模块名称 现在做的是登录功能.因此扩展模块名叫 login 使用layui ...
- Wx-小程序-图片预览、保存
点击图片预览 长按图片保存 点击按钮保存到手机相册 view: <!--wxml--> <text>点击图片预览.长按保存图片.点击按钮保存到系统相册</text> ...
- [BPNN]BP神经网络实现
BP神经网络实现 以3层网络为例,Python实现: 1.代码框架 主要函数: Init函数:设定InputLayer nodes.HiddenLayer nodes.OutputLayer node ...
- java用JSONObject生成json
Json在前后台传输中,是使用最多的一种数据类型.json生成的方法有很多,自己只是很皮毛的知道点,用的时候,难免会蒙.现在整理下 第一种: import net.sf.json.JSONArray; ...
- Rsync+inotify数据同步
安装环境 备份服务器端:CentOS7,IP:192.168.1.100 备份客户端:CentOS7,IP:192.168.1.200 服务器端Rsync服务部署 1.安装程序包 # yum –y i ...
- 【译】高级T-SQL进阶系列 (四)【上篇】:使用游标进行行级别处理
[译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 正常来说,使用游标并不是处理记录集的最佳方式.然而当一个经验丰富的程序员第一次开始写TSQL时,他们经常会寻找其 ...
- iOS 实现 摇一摇
摇一摇功能:调用了系统自带加速器,当设备摇动时,系统会 计算出加速器的加速值,然后告诉设备是否发生摇动手势,系统只会运动开始和结束时通知你,并不会在运动发生的整个过程中始终向你报告每一次运动.例如,你 ...