转自:设计模式是什么鬼(单例)

之前我们讲过面向对象以及封装、继承、多态三大特性,底子打好了那我们就把设计模式一个个拆开来看看到底都是神些什么鬼,我们先从简单的单例说起吧。单例,顾名思义,整个系统其实就只有一个实例存在,不能再多,否则就不叫单例。那我们把整个宇宙看做是一个庞大的系统,这宇宙里有各种对象存在,人啊,动物啊,植物啊不胜枚举,这些都是实例,丰富多彩的世界是美好的。然而,持续几千年的战争给世界带来了巨大灾难,尤其是宗教战争最为残忍,各个信仰间存在极大的世界观价值观冲突。

单印度一个国家就有几百个神,人们各信各的,风俗各异,各邦文化冲突不断,语言不通,办事效率极低。

为了让幸福美好洒满人间,那我们就定义一位神吧,独一无二的神。

我们先写一个God类吧,类中空空如也,世界如此清净,虚无缥缈。

public class God {}

首先我们得保证任何人都不能去创建神的实例,否则如:new God(),这样世界又要陷入战争的灾难,各种造神运动,或是某天又出来个什么神棍先知告诉信徒说他们肚子里有个轮子。那就不写构造方法吧?不行,因为有默认的无参构造器!那就把构造方法改成private吧,也就是神可以自己创造自己,但别人不能。

public class God {private God(){}//构造方法私有化
}

God类里面封装一个God自己,对,一切都是神创造的,包括我们人类。有人开始质疑,那神是谁?神自己是谁造的?这是个哲学问题。神说“I am who I am.” 我是我所是,我就是我,自有永有,超越时空。很逆天吧? 好吧,谁也不能造上帝,神自己造自己。

public class God {private static final God god = new God();//自有永有的神单例private God(){}//构造方法私有化
}

以上private关键字保证了上帝的私有性,不可见性,不可访问性,我想没有活人见过上帝吧?static关键字保证上帝的静态性,他与类同在,不依赖于类的实例化就自有永有,他将在内存中永生,GC垃圾回收器也回收不了他。final关键字则保证这位神是和常量,衡量,他是终极上帝,不能再改。

正如同静态方法main(),不需要实例化类就能运行的入口,同样我们需要一个静态方法getInstance()来请神,方法体内我们就返回这个在唯一的真神,当然方法它必须是public公开的,不然谁都访问不了。

public class God {private static final God god = new God();//自有永有的神单例private God(){}//构造方法私有化public static God getInstance(){//请神方法公开化return god;}
}

以上的神类雏形已经写好了,当然你还可以加其他的功能方法,比如说创世纪神造了光,造了世界、动物、人、亚当夏娃等等功能,我们这里就不在赘述了。那对于外部来说只要调用God.getInstance();就可以拿到神了,而且不管谁拿,拿几次,都是同一个神,这样就保证了整个系统中神的唯一性,不可伪造性,至于其他先知那也只是神的代理人,只能帮请神而已。

好了,其实我们已经学会了单例模式的“痴汉模式(Eager load)”,代码第一行一开始就造出了神(new God那一句),已经准备好了随时给你请神,这样就有了一个问题,如果没人请神那不是白造了?提前备货如果价格跌了不是很惨?反应在系统中的问题就是占用了内存空间。于是又有了“懒汉模式(Lazy load)”

public class God {private static God god;//这里不进行实例化private God(){}public static God getInstance() {if (god == null) {//如果无神才造神god = new God();}return god;}
}

这我们看到一开始就没有造神,只有某人第一次求神时才实例化,之后再求的就直接返回了。这样的好处是省了一段时间的内存(无求神期间),坏处是第一次请神的时候速度相较之前的痴汉模式会慢,因为要消耗CPU去造神。

其实这么写是在多线程模式下是有陷阱的,试想多人同时并发请神的话,依然会造成多神,好吧我们再来改良一下,把请神方法加上synchronized,声明为同步方法,某线程调用前必须获取同步锁,调用完后会释放锁给其他线程用,也就是请神的必须排队,大家一个一个按顺序来。

public class God {private static God god;//这里不进行实例化private God(){}public static synchronized God getInstance() {//此处加入同步if (god == null) {//如果无神才造神god = new God();}return god;}
}

然而,这样做是要付出代价的,还没进庙呢不管三七二十一请神的直接给加锁排队,结果队伍从北边的庙排到了南天门,人们都要来一个一个拜佛求神,这造成了巨大时间浪费,没有充分利用CPU资源并发优势(特别是多核情况)。好吧,那还是让人们抢好了,但依然得保证单例神的情况下。

这里我们去掉方法上的同步关键字,换到方法体内部做同步,整个方法开放并发大家都可以同时入庙,当然起早贪黑的虔诚信徒们要抢头香是必须要入堂排队的。一旦头香诞生,那其他抢香的都白早起,白排队了。再之后的事情我们都可以预见了,头注香被抢后堂内排队再无必要来了,大家可以在堂外同时并发拜佛求神,这就极大的利用了CPU资源。简而言之:只有第一批抢头香的在排队,之后大家都不必排队了,代码如下。

public class God {private volatile static God god;private God(){} public static God getInstance() {//庙是开放的不用排队进入if (god == null) {//如果头柱香未产生,这批抢香人进入堂内排队。synchronized(God.class){if (god == null) {//只有头香造了神,其他抢香的白排队了god = new God();}}}//此处头柱香产生后不必再排队return god;}
}

其实在这之上还发展出了各种各样的单例模式变种,我们这里只讲了最基础的两种,其实他们都各有优缺,我们要做到灵活运用,各取所需。对于我个人来讲倾向于懒汉模式,现在内存成本根本不算问题,况且迟早要被实例化占用内存,加锁解锁更是一种浪费,还有同步效率低等问题,如果上帝不是很占空间那就没必要去懒汉延迟加载,越复杂问题越多,风险越大。

大道至简,无为而治。

设计模式是什么鬼(单例)相关推荐

  1. 设计模式C#描述——单例与多例模式

    设计模式C#描述--单例与多例模式 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式有以下特点: 单例类只能有一个实例. 单例 ...

  2. 设计模式学习笔记——单例(Singleton)模式

    设计模式学习笔记--单例(Singleton)模式 @(设计模式)[设计模式, 单例模式, Singleton, 懒汉式, 饿汉式] 设计模式学习笔记单例Singleton模式 基本介绍 单例案例 类 ...

  3. JAVA设计模式什么鬼(单例)——作者:凸凹里歐

    之前我们讲过面向对象以及封装.继承.多态三大特性,底子打好了那我们就把设计模式一个个拆开来看看到底都是神些什么鬼,我们先从简单的单例说起吧.单例,顾名思义,整个系统其实就只有一个实例存在,不能再多,否 ...

  4. iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  5. 单例设计模式-Enum枚举单例、原理源码解析以及反编译实战

    package com.learn.design.pattern.creational.singleton;/*** 这个类是Enum类型* 这个枚举非常简单* 枚举类是Object* 他在多线程的时 ...

  6. java中单例设计模式登记式单例类_java23种设计模式-创建型模式之单例模式

    单例模式(Singleton) 单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频 ...

  7. 多个if用什么设计模式_抽丝剥茧——单例设计模式

    单例设计模式 兄弟们好,今天是最后一个设计模式了,也是我们最熟悉的单例设计模式,可以说这个设计模式是我们最先接触到的设计模式了.想当年学习JavaSE的时候,老师聊到一个「饿汉式和懒汉式」,我还纠结了 ...

  8. 设计模式之简单单例设计模式

    参考资料:[作者:刘伟  http://blog.csdn.net/lovelion] 单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 ...

  9. python 与设计模式 ——工厂与单例

    python 与设计模式 源码地址:http://git.oschina.net/duoduo3_69/python_design_pattern git checkout v001(这个版本与此篇博 ...

  10. JS 设计模式 四(单例)

    单例 单例是一个全局变量,使用单例可以更好的控制全局变量,还可以利用分支技术来封装浏览器之间的差异.网页中使用全局变量由于可以被重写风险很大.所以使用单例会更好的控制全局变量. 懒加载 单例模式多数都 ...

最新文章

  1. 如何将yolo的标注(annotations).txt 坐标转换成tensorflow-yolov3(YunYang1994)的.txt 标注坐标?
  2. 三种常见字符编码简介:ASCII、Unicode和UTF-8
  3. GG and MM(every sg 游戏)
  4. github上打包的样式为什么在预览的时候,出现404
  5. PetShop4.0--转载
  6. mybatis mysql 调用存储过程 多个返回值_MyBatis的SQL执行流程不清楚?很简单!
  7. Fuel 9.0安装的Openstack Controller节点进程整理
  8. Resumable.js - 基于HTML5 File API的可断点续传的文件上传插件
  9. 海思3159A运行yolov3(二)——yolov3模型转caffemodel模型
  10. ubuntu内核和主线内核_如何在没有任何Distro-upgrade的情况下将内核更新到最新的主线版本?...
  11. ccccccccccccccccccccc
  12. 软件质量 软件测试和质量保证
  13. java 生成ai矢量图,PS和AI将图片转成矢量图
  14. icesword介绍
  15. Unity内置Shader解读10——Self-Illumin/Bumped Diffuse
  16. DS18B20的CRC验证算法
  17. Win10电脑的快捷键有哪些?Windows10常用组合快捷键大全
  18. 易语言 网页_取文本_reg的源码
  19. 赵小楼《天道》《遥远的救世主》深度解析(116)论天国的女人
  20. eset找不到服务器更新失败,ESET NOD32连接到服务器以更新常见的错误检测方法

热门文章

  1. 库克看下!罗永浩深夜再谈收购苹果:还需要点时间
  2. 苹果屏幕供应商JDI正寻求中国投资 因国内面板厂商正在崛起
  3. 2018年智能手表出货量曝光 苹果Apple Watch占据半壁江山
  4. 985材料研究生转行自动化,收割一众大厂,拿到54w的工作
  5. 晨哥真有料丨及时止损的信号及可能的挽回方法
  6. case when then else_每天一个常用MySQL函数-[case_when_then_end]
  7. 创建型模式、结构型模式和行为型模式_设计模式之创建型模式
  8. asp.net 用户注册怎么判断用户名是否重复 ajax,AJAX_asp.net结合Ajax验证用户名是否存在的代码,1, 使用JavaScript js文件,验证 - phpStudy...
  9. 我的docker随笔28:基于容器的升级方案实验
  10. Golang实践录:调用C++函数的优化