设计模式(单例模式)
来源:互联网 发布:java web开发实战 编辑:程序博客网 时间:2024/06/08 08:55
单例模式
在决定写设计模式系列博客前我慎重的考虑了一番,首先网上关于设计模式的文章实在是太多了,很难写出什么特色,再者我觉得自己水平比较有限不知道能不能写好。可是思虑了很久我还是决定写一个设计模式的系列,别人写的东西也许能看懂但不一定就真的会了,就算是会了也不一定就能正确的使用,同是打狗棒法,洪七使出来和丐帮的弟子使出来那完全不是一样的境界和效果,所以我决定自己搞一遍,加深理解。
Design.Patterns中单例的定义:
Ensure a class only has one instance, and provide a global point of access to it.
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
学习单例模式的时候我一直在想,为什么要搞出来一个单例模式呢?想来想去发现这么搞还是有些道理的,面向对象本质上是对现实世界的模拟,而现实世界中有些东西确实是不能有两个或多个的,或者在一定的范围内有些东西是不能有多个的。自古就有一山不容二虎之说,设计模式之禅中举了一个很好的例子,那就是一个国家只能有一个皇帝,不能有多个,一旦有多个皇帝那肯定是要打仗的。在程序中也一样,有些类是不能有多个实例的,比如统计网站的访问次数,你能用多个对象去统计吗?再比如电脑中的任务管理器,你能搞多个任务管理器来管理这些进程吗?再比如程序日志的追加,你能搞多个对象去同一个文件中追加日志信息吗?要是非要较真我觉得技术上肯定有办法实现的,但是搞起来怕是会很费劲的。我们可以用生活的角度来思考程序,有些事情就是一个人干的,你安排两个人肯定会有问题的,程序也是一样,有些事情就是只能由一个实例完成的就不要搞多个实例。单例模式就是在你需要用到这个实例的时候给你提供这个实例,而且不论谁用我都给你的是同一个实例。
请看下面代码
public class Singleton {}
public class SingletonProvide { private static final Singleton singleton = new Singleton(); public static Singleton getInstance() { return singleton; }}
我们的目的就是在程序的任何地方使用同一个Singleton对象,从功能上看这段代码完全满足了我们的使用需求,没有问题吧?功能上我觉得是没有问题,但是开发中就有问题了,开发往往是一个团队,如果某个人不知道Singleton是单例的或者他知道但是就是想搞点破坏,他自己创建了一个Singleton或者SingletonProvide,那就不能保证程序中只有该类的一个实例了。因此代码就要写成下面的样子。
单例实现一(饿汉式线程安全)
public class Singleton { private static final Singleton singleton = new Singleton(); // 构造函数私有让想搞破坏的人无法创建对象 private Singleton() { } public static Singleton getInstance() { return singleton; }}
这个就是比较中规中矩的单例模式的实现了,设计模式之禅中也比较推荐这种实现方式,因为singleton是静态的不用考虑多线程问题。缺点就是类加载时就要初始化,比较浪费内存,当然了,都什么年代了,电脑内存那么大跑那么快,浪费一点也没关系,可以这么用的。
单例实现二(懒汉式非线程安全)
public class Singleton { private static Singleton singleton; // 构造函数私有不让想搞破坏的人创建对象 private Singleton() { } public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; }}
这种实现在单线程下是没有问题的,但是在多线程下就可能创建多个实例对象,解决多线程也比较简单同步一下就好了,代码如下。
单例实现三(懒汉式非线程安全)
public class Singleton { private static Singleton singleton; // 构造函数私有不让想搞破坏的人创建对象 private Singleton() { } // 对获取实例的方法进行线程同步 public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; }}
但是对一个方法说同步就同步了,是不是太草率了?synchronized的作用范围内代码是越少越好,所以我们把创建过程进行同步就行了,下面就是双层查锁的单例实现。
单例实现四(双层查锁线程安全)
public class Singleton { private volatile static Singleton singleton; // 构造函数私有化,不让外部创建对象 private Singleton() { } // 双层查锁 public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; }}
细心的同学会发现多了一个volatile关键字,这玩意牵扯的东西太多了,我不想讨论这玩意,这么用就行了,当然了,不推荐这么玩。
单例实现五(Holder式线程安全)
这个是我比较推荐的,设计的很巧妙
/** * 用抽象类防止通过反射创建类的实例 * @author liujh_2017-10-21 */public abstract class Singleton { // 内部类提供实例,完成了懒加载 private static class PrinterHolder { private static final Singleton INSTANCE = new Singleton() { }; } // 获取类的实例 public static Singleton getInstance() { return PrinterHolder.INSTANCE; }}
常见的单例模式的实现大概就是这些,还可以通过枚举来实现单例,我也试了一下,但是我这里不想对这种实现方式进行讨论,枚举我没怎么用过,怕误导大家。
参考资料:
1.设计模式之禅
2.Design.Patterns.Elements.Of.Reusable.Object.Oriented.Software
3.Design.Patterns中文版
4.Effective Java(第2版)
- 设计模式(单例设计模式)
- 设计模式(单例设计模式)
- 设计模式之单例设计模式(饿汉单例设计模式&懒汉单例设计模式)
- 设计模式(工厂模式、单例模式、模板模式)
- 设计模式(单例模式,工厂模式,适配器模式)
- 设计模式---单例模式(singleton)
- 设计模式--单例模式(Singleton)
- 设计模式(1)-单例模式
- 设计模式(1):单例模式
- 模式设计(二)------单例模式
- 设计模式(四)---单例模式
- 设计模式--单例模式(Singleton)
- 设计模式(单例模式)
- 设计模式(1):单例模式
- 设计模式-单例模式(Singleton)
- 设计模式(一) 单例模式
- 设计模式(三)单例模式
- 设计模式(1):单例模式
- quartz集成spring
- JavaEE学习笔记之Servlet
- HDU 5934 强连通分量
- 2017CCPC哈尔滨滚粗记
- solrCloud 集群搭建
- 设计模式(单例模式)
- const&内联&友元
- 网络层的协议
- 5位运动员参加了10米台跳水比赛,预测比赛结果
- Python学习(1)--变量与表达式
- 关于re.match()返回<_sre.SRE_Match object; span=(0, 5), match='trfgr'>的处理
- 洛谷 P1902 刺杀大使
- 【工具】hcash超级现金挖矿收益计算器
- [Asp.net]生成dll(动态链接库)