常见设计模式—单例模式(Singleton)
前言
好久没写东西了,但是想着无论什么事还是要坚持自己初心要坚持的东西。写东西不能断!
对于常用的23种设计模式,这里笔者会根据自己学习和出现频率、重要程度进行学习记录吧。并且每种设计模式可能会根据暂时需求侧重学习深浅。
单例模式
有很多直接把单例分成很多种,这里我就分两个大类(饿汉懒汉)在这里说啦。
单例模式(Singleton Pattern)是设计模式中最简单的模式之一,属于创建型
模式。这种设计模式主要是类的对象只有一个实例,不需要每次new 创造。而我们要做的的就是确保这个对象创建的唯一
。然后根据一些特征进行优化创建以及访问改类。
而单例模式也有很多的应用,比如很多驱动例如摄像头、打印机等等,而在javaweb中的spring有很多配置文件,掌控全局,同样也是单例的。
对于单例,主要是全局只有这么一个对象。对了它的理解,这里笔者打几个有可能不太恰当的理解,目的在于帮助理解记忆,如果有错误还请指正。
个人可能不太恰当的理解:
- 一定程度上单例模式和普通的模式有可能是一根根火柴和打火机的差别。火柴想燃烧每次都要一根火柴摩擦燃烧为灰烬作为代价。而一个打火机可以持续供给。同样如果你只想在某个线程某个类想要得到执行改类的一个方法,如果这个类占用的内存、空间巨大,耗费的时间也很大的话,如果频繁创造是一笔很大的负担,那样就不如咱们就创建好一个然后供我们使用就好啦。
- 一定程度又像是他人和个人的区别。每个人都可能干过相同的事情,可能很多人都在校园的跑道上跑过步,但他们并不是你,你也可能在操场上跑过很多圈。但只有你知道你的思考。同样单例模式在一定程度可以看作一个人生,它可能有很多职能,也可能干过很多事、重复过很多事。但它可能对自己有从始至终的思考和记录。它可能有些全局参数记录着程序从始至终一些状态、信息等等。也就是它一直是它,你也一直是你独特的自己。
- 其他等等
至于单例模式的优缺点,这里就不作详细介绍了。无非是关于性能职能
、时间
、空间
、拓展性
等方面的一些讨论。这个可以参考不同人的不同理解。本文主要记录单例模式的实现方面。而同样单例模式实现上分为饿汉式和懒汉式:
单例模式创建要求:
- 某个类只能有一个实例(构造器私有化)
- 它必须自行创建这个实例(含有一个改类的静态变量来保存这个唯一的实例)
- 自行向整个系统提供这个实例(
直接暴露
或者用静态变量的get
方法)
饿汉式
直接创建对象,不存在线程安全问题 。对于饿汉式的实现是相对简单和容易的。在实际遇到这种类似的思想其实也很多。
理解:
- 这个饿汉式就好比双十一,你一下把你家里感觉可能缺的日后可能需要(也不一定需要的)全部给买了。比如啥洗衣液屯、棉衣棉鞋棉被日后可能要买也买。然后啥微波炉、烤箱我
感觉可能
以后会用我也买买买。买买买。这一下就买全了。但是:
- 同样在实际的生产,我们一个项目中可能有很多这样单例的存在,如果一次性启动的话对时间花销真的是太大。可能对程序的压力和体验都很差。所以一般很少直接使用。这种体验,像极了你打开某个网页等待JavaScript和css的过程。
饿汉式的几种实现方式:
01 . 直接实例化饿汉式(简洁直观)
/*** 饿汉式* 直接创建实例,不管是否需要这个对象*/
public class singleton1 {public static final singleton1 INSTANCE = new singleton1();private singleton1(){}
}
02 . 枚举式(最简洁)
public enum singleton2 {INSTANCE
}
03 . 静态代码块饿汉式(适合复杂实例化)
public class singleton3 {public static final singleton3 INSTANCE;static {/**** 有可能一些数据需要配置,需要从类加载器加载* 例如从某xxx.properties加载某些配置信息,我们只需更改配置文件不需要更改代码*/INSTANCE=new singleton3();}private singleton3(){}
}
懒汉式
我们知道饿汉式在早早把对象创建好,在执行一些其他逻辑时候不存在线程安全的问题。但是懒汉式就不一样啦,延迟创建对象可能会有线程安全问题。
01 .线程不安全(适合单线程)
/**** 懒汉式:构造器私有化* 静态变量保存实例* 提供一个静态方法,获取这个实例对象*/
public class singleton4 {private static singleton4 instance;private singleton4(){}public static singleton4 getInstance(){if (instance==null)instance = new singleton4();return instance;}
}
对于这种单线程没问题,但是如果如果两个或多个线程来同时访问instance如果都为null同时申请的时候会遇到下图等之类问题,这违背了单例模式的设计原则并且可能会对系统数据造成错误。
02 .线程安全(适用于多线程)
怎么优化上述的懒汉式单例模式呢?既然不允许多个线程这样同时访问,那么咱们给它上个锁不久行了嘛!
public class singleton5 {private static singleton5 instance;private singleton5(){}public static singleton5 getInstance(){synchronized (singleton5.class){if (instance == null)instance = new singleton5();}return instance;}
}
但是这样有啥问题呢?就是我获取这个单例对象的时候,被上锁了。你气不气?我们就是在创建这个单例时候多线程可能出现点问题,咱么获取的时候不存在线程安全问题啊。。你为啥获取也要锁??
这就好比,咱们都喜欢看美女,跟美女说话要排队一个一个来,只能一个在一个时刻,但是你看美女不需要排队啊!!!
03 .线程安全推荐版(适用于多线程)
对于上述存在的问题,咱们只需要双重判定就行了。
- 首先判断instance是不是为null。如果不是null说明被实例化过直接返回即可!nice!
- 如果instance为null?上锁之后再判空实例化。
public class singleton6 {private static singleton6 instance;private singleton6(){}public static singleton6 getInstance(){if(instance==null) {synchronized (singleton6.class) {if (instance == null)instance = new singleton6();}}return instance;}
}
两个判断为null?为啥要两个?
- 第一个:用来判断是否为空需要上锁new 实例。
- 第二个:上锁后虽然只有一个会执行当前方法,但是很可能都为null的时候两个或多个都为null上锁的想构造。然后后面线程在等待同时前面线程构造好了,那么它就不需要再去构造这个
instance
啦!直接不操作就行了。
就这样,稍微完美的方法就这样产生了。
04 .静态内部类形式(适用于多线程)
上面的方法可能有些复杂,而静态内部类也是个好方式。主要是静态内部类和外部类不是一起加载的,并且你去调用它的时候他就会初始化,并且类加载是线程安全的,这个不需要考虑线程安全问题。当加载完之后你就可以直接拿啦。这样也能达到延迟加载的作用。
这个更详细你可以自己研究静态变量(类变量)、静态内部类等等加载顺序,研究下`static关键字。
public class singleton7 {private singleton7(){}private static class inner{private static final singleton7 instance=new singleton7();}public static singleton7 getInstance(){return inner.instance;}
}
结语
学习参考尚学堂单例讲解以及百科、菜鸟教程等等,有些区别但是大部分实现都是相似的,带上个人理解分享给大家。如果有问题和疏漏还请指教!
欢迎交流学习、欢迎关注微信公众号:bigsai
常见设计模式—单例模式(Singleton)相关推荐
- Android设计模式——单例模式(Singleton)
二十三种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元 ...
- 设计模式 -- 单例模式(Singleton)
写在前面的话:读书破万卷,编码如有神 -------------------------------------------------------------------- 主要内容包括: 初始单例 ...
- C++设计模式--单例模式(Singleton)及单例通用模板
概述 C++中的单例模式应该是设计模式中最简单的了,在编码中常见到.那么,简单的总结下 C++中的单例模式写法,以及根据单例模式扩展后的一些写法,最后还有单例的通用模板,可用于快捷创建一个单例类. 单 ...
- 设计模式——单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点.--DP UML类图 模式说明 个人认为单例模式是所有设计模式中最为简单的一个模式,因为实现这个模式仅需一个类,而不像其他模式需要若干个类.这个模 ...
- Python 设计模式: 单例模式(singleton pattern)
2019独角兽企业重金招聘Python工程师标准>>> 如果想在整个程序的运行过程中,某个类只有一个实例的话,可以通过单例模式来实现. 在 Python 中实现单例模式有很多种方式, ...
- 趣谈设计模式 | 单例模式(Singleton) :独一无二的对象
文章目录 单例模式 饿汉模式 懒汉模式 懒汉和饿汉的区别 单例模式 一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全 局访问点,该实例被所有程序模块共享. ...
- 解读设计模式----单例模式(Singleton Pattern)
单例模式可以保证一个类有且只有一个实例,并提供一个访问它的全局访问点.在程序设计中,有很多情况需要确保一个类只能有一个实例.从这句话可以看出,Singleton模式的核心:如何控制用户使用new对一个 ...
- JAVA设计模式-单例模式(Singleton)线程安全与效率
一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...
- 设计模式---单例模式Singleton
/*** 饿汉式* 类加载到内容后,就实例化一个实例,* JVM保证线程安全: JVM保证每一个Class只会load到内存一次,static关键字是在Class load到内存之后马上就行初始化,也 ...
最新文章
- 20180320作业1:源代码管理工具调查
- 违反了primarykey约束怎么解决_前期物业服务合同对主业有约束力吗?
- ELK logstash 配置自定义字段为索引
- RocketMq Consumer 最佳实践
- 基准测试 ApacheBench ab学习
- android 左右卡片切换,3D卡片切换
- linux c语言编写聊天室mysql_Linux平台上用C语言实现与MySQL数据库的连接
- BeanPropertyRowMapper使用注意事项
- Postman的使用说明
- 最高月薪25K!一周收到7个15K以上的offer,他是如何做到的?
- 地产行业信息化建设思考
- 软件测试之测试报告案例
- Appium自动化测试元素定位方式
- 微软宣布 IE 浏览器将于 6 月 16 日正式退役,你对它有哪些回忆?
- 第五次作业:项目分类
- TCP/IP, WebSocket 和 MQTT
- 从光学成像到计算光学成像
- 北京大学 李胜 计算机,rasterization-北京大学计算机系图形与交互技术室.pdf
- 【POJ No. 3104】 烘干衣服 Drying
- Unity3D相关知识点笔记汇总
热门文章
- C++ Primer 5th笔记(chap 18 大型程序工具)noexcept
- 【Opencv实战】这个印章“神器”够牛,节省了时间提高了效率,厉害~(附完整源码)
- 《极速切水果游戏》有Python版了,曾风靡一时的手游能否富过“二代”?
- Android keystore/Keymaster的代码导读
- Docker核心原理之cgroups
- nedmalloc结构分析
- 使用 rsync / scp 命令下载linux文件,显示网速和进度
- CS起源pointermap找基址+工具函数测试
- 花指令——多个指令共用字节
- 2017年CISCN初赛