老王讲设计模式(三)——单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。
早晨,老王来到公司,发现小蔡正对着电脑屏幕发呆,于是走到小蔡身后,发现小蔡正对着一个宝宝照发呆。
老王拍了一下小蔡肩膀,问:“这个是谁啊?没听说你有男朋友啊。难道是私生子?”
小蔡回头,呸了老王一下,说:“这是我二表姑的侄子的姐夫的姑姑的妹妹的舅舅的儿媳妇的堂哥的娃娃。”
老王还没回过神来,小蔡又说:“宝宝真可爱,要是我以后要宝宝了,我一定只要一个,我要带她到处去耍,给他买各种漂亮的衣服,各种好玩的玩具,各种吧嗒吧嗒吧嗒……(此处省略数千字)”
老王心想:“都说一个女人等于500只鸭子,这个小蔡何止500只鸭子,简直就是5000只鸭子,而且全是话痨型鸭子。”
老王趁小蔡两句话之间喘气的时机,赶紧打断了小蔡:“你说到只要一个宝宝,我给你讲讲程序代码只要一个宝宝的方法,好不?”
小蔡一听,很好奇:“程序代码,也有一个宝宝的说法?”
老王说眼看将话题转移了,赶紧接着说:“是啊,那就是单例模式,它可以让整个程序系统里,只存在唯一的实例对象。从而大幅节省内存资源。”
老王不给小蔡搭话的机会,紧接着演示起了代码:“单例模式,分为懒汉式和饿汉式,我们先来看看懒汉式。”
//懒汉式
public class Lazybones {//实例对象private static Lazybones instances = null;//私有的构造函数,阻止实例化对象private Lazybones(){}//如果发现没有实例对象,就构造一个//如果有实例对象,直接返回public static Lazybones getInstances(){if(instances == null){instances = new Lazybones();}return instances;}
}
小蔡很好奇,问:“代码也有懒汉?”
老王说:“对啊,在使用到的时候才实例化,这就叫懒汉式。这种方式有个好处就是在不使用的时候不会占用内存空间。但是这里也有一个问题。”
小蔡问:“什么问题啊?”
老王说:“在大并发,多线程的环境下,假如有多个线程同时执行到getInstances()
方法,第一个线程执行if
语句,还没有完成构造时,第二个线程也执行到if
这里,这时候instance
依然为空。这样线程一和线程二会同时产生两个实例。所以懒汉式的单例模式,并不是线程安全的 。”
小蔡又问:“难道饿汉式是线程安全的?”
老王说:“对的,饿汉式单例模式的确是线程安全的。咱们来看代码。”
//饿汉式
public class Hungry {//不管三七二十一,直接实例化一个对象private static Hungry instances = new Hungry();//私有的构造函数,阻止实例化对象private Hungry(){}//直接返回已经实例化了的对象public static Hungry getInstances(){return instances;}
}
老王说:“你看,饿汉式单例模式,不管是否使用,直接就将对象实例化在那儿放着,要用的时候直接使用,这样就不用再去判断,所以饿汉式单例模式是线程安全的。”
小蔡问:“老王,我们怎么验证这个这个对象是否单例呢?我们又看不到内存里的分配情况。”
老王说:“这个我们就得靠对象的哈希码了。因为哈希码是用来在散列存储结构中确定对象的存储地址的。简单理解,就是一个对象的hash code和内存地址是一一对应的,只要hash code值相同,那么就是同一内存地址。在Java里,一个对象的toString()
方法默认返回这个对象的hash code。我们来看代码。”
public class SingleCheck {public static void main(String[] args) {//通过饿汉式单例模式,获得3个对象Hungry h1 = Hungry.getInstances();Hungry h2 = Hungry.getInstances();Hungry h3 = Hungry.getInstances();//打印其Hash codeSystem.out.println("h1:" + h1);System.out.println("h2:" + h2);System.out.println("h3:" + h3);//通过懒汉式单例模式,获得3个对象Lazybones l1 = Lazybones.getInstances();Lazybones l2 = Lazybones.getInstances();Lazybones l3 = Lazybones.getInstances();//打印其Hash codeSystem.out.println("l1:" + l1);System.out.println("l2:" + l2);System.out.println("l3:" + l3);}
}
其结果为:
老王说:“从结果,我们可以看到,通过getInstances()
方法得到的对象,无论获取多少次,的确为同一对象。这里我再说一下单例模式的关键点:1. 私有的构造函数,防止从外部构造对象。2. 静态的私有变量存储对象。3.共开的获取对象的方法。通过这三点,就可以完成单例模式的编写,通过运用单例模式,我们可以避免重复构造对象,从而节省系统的内存资源消耗。”
小蔡说:“老王,这就是你说的只有一个宝宝的代码?”
老王说:“对啊。正是。”
小蔡眨了眨眼,又问:“那如果我不止想要一个宝宝呢?现在国家政策放开了,可以要两个宝宝了。”
老王说:“那你就得先找老公了呀。”
小蔡怒道:“我问的是代码!只要2个宝宝的代码!”
老王笑道:“那就是多例模式,我们下回再讲。”
老王讲设计模式(一)——策略模式
老王讲设计模式(二)——代理模式
老王讲设计模式(三)——单例模式
老王讲设计模式(四)——多例模式
更多内容,正在赶来,敬请关注“小蔡和老王的技术日常”。
PS:小蔡和老王的技术日常,已经建立QQ群,QQ群号:261434596,欢迎加入。
老王讲设计模式(三)——单例模式相关推荐
- 老王讲设计模式(八)——适配器模式
适配器模式,是作为两个不兼容的接口之间的桥梁.这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能. 公司的发展速度很快,一不小心,就收购了一个创业团队去做细分市场.这么一个改变,对于公司来说 ...
- 老王讲设计模式(一)——策略模式
策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 老王最近接到一个工作,上 ...
- 四象限法推导lm曲线_【老王讲放射】四象限理论
FCR的研发者之一高野正雄将CR系统影像处理的运行原理归纳为"四象限"理论,EDR(曝光数据识别器)的功能和CR系统工作原理可以用"四象限"理论进行描述. 1. ...
- zemax中非序列添加相位面_老王讲放射MRI脉冲序列的基本参数
今天这篇重点也是考师或中级的重中之重,里面比较多的字母代号,务必记好.有些人可能不知道,考试的时候这些重点可能会以什么样的方式出现? 那么我今天在每个重点后面都添加了问题,以供大家参考! 磁共振序列参 ...
- 我和王争学设计模式 |单例模式
目录 前言 定义 特点 适合场景 实现 总结 极客时间<设计模式>(王争) PHP codes on Gitee PHP codes on Github 前言 开始补全木桶最短的一片了,跟 ...
- 老王讲二进制 0xFF;
$a = 2; $b = ($a<<6) & 0xFF; var_dump($b);die; 代码如上 最后结果是 128 . $a 二进制 左移6 位 相当于 $a * ...
- 马上2021年了线性表你还不知道原理?给老王整的明明白白
文章目录 一.线性表必知必懂的原理 (一)线性表通俗易懂原理 二.线性表对数据的操作 (一)增加操作(老王插队神操作) (二)删除操作(小明取完票让位给老王) (三)查找操作 三.单链表案例 (一)案 ...
- java 的23种设计模式 之单身狗和隔壁老王的故事
2019独角兽企业重金招聘Python工程师标准>>> 觉得代码写的别扭了,回头翻翻java 的23种设计模式. today,额,这么晚了,困了.就弄个最简单的单例模式吧. 单例模式 ...
- java 从入门到单身狗_java 的23种设计模式 之单身狗和隔壁老王的故事
觉得代码写的别扭了,回头翻翻java 的23种设计模式. today,额,这么晚了,困了.就弄个最简单的单例模式吧. 单例模式:俗称单身狗 package singleton; public clas ...
最新文章
- java与c/c++之间的数据交互-----jni点滴
- RabbitMQ (四)实现延迟消息
- bzoj 2748: [HAOI2012]音量调节
- 使用HTML5开发离线应用 - cache manifest
- 怪咖发明家,乔布斯给了他四亿,他没要,转身靠发明救了10亿人。
- android 双向滑动 seekbar
- 知识小结(浮点数问题)
- 2021抚顺高考成绩查询,2021年抚顺高考成绩排名及成绩公布时间什么时候出来
- android 系统(154)----OTA制作及升级过程
- java单例模式_Java 实现单例模式的 9 种方法
- python基础编程语法-编程入门02:Python基础语法
- PHP文件可限速下载代码
- 如何在dorado中自定义导出
- 《Android开发艺术探索》第7章- Android 动画深入分析读书笔记
- 22一战上岸首师大电子信息经验分享|低成本获得大收益|电子信息
- openstack-ocata版本nova MQ(rpc)接收端(server)浅析
- git 修改命令 VI
- 2014-04《信息资源管理 02378》真卷解析,逐题解析+背诵技巧
- 请你谈谈IP地址和MAC地址关系,为何需要两个地址?
- Problem Set 2 Hangman Game字谜游戏
热门文章
- python模拟浏览器代码_python 模拟浏览器
- 无处 不在的无线智能——6g 的关键驱动与研究挑战_一文看懂什么是 6G
- python发送邮件有逗号_Python发送邮件
- springbatch读取文件_通过例子讲解Spring Batch入门,优秀的批处理框架
- webpack文件系统缓存
- 找不到php fpm.pid,找不到文件nginx php-fpm
- linux开启新的一行,linux启动ekp脚本【一行命令重启ekp】
- mysql强制指定索引_mysql强制索引和禁止某个索引
- oracle 分区表转换,Oracle 12.2之后ALTER TABLE .. MODIFY转换非分区表为分区表
- mysql.sys用户权限_MySQL用户及权限小结