在刚学编程没多久就据说过设计模式的大名,不过因为当时仍是个不折不扣的菜鸟,并无去触碰。直到在开始工做中对简单的业务代码较为熟悉以后,才正式的接触设计模式。当时最先接触的设计模式是工厂模式,不过本文讲的是单例模式,这里就留着下篇文章中在讲解。至于为何先讲解单例模式? 那是由于单例模式是设计模式中最简单的... 。凡事总有个前后顺序,因此就先易后难了。好了,废话很少说了,开始进入正片。数据库
说明:这里说了的简介就是真的 “简介”。编程
设计模式是一套被反复使用的、多数人知晓的、通过分类编目的、代码设计经验的总结。设计模式
使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。安全
设计模式有23种类型。按照主要分类能够分为三大类:多线程
1、建立型模式性能
这些设计模式提供了一种在建立对象的同时隐藏建立逻辑的方式,而不是使用 new运算符直接实例化对象。这使得程序在判断针对某个给定实例须要建立哪些对象时更加灵活。学习
2、结构型模式.net
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象得到新功能的方式。线程
3、行为型模式设计
这些设计模式特别关注对象之间的通讯。
设计模式的六大原则
保证一个系统中的某个类只有一个实例并且该实例易于外界访问。例如Windows界面的任务管理器就能够看作是一个单例。
在程序中比较经常使用的是数据库链接池、线程池、日志对象等等。
最先咱们在学习单例模式的时候,基本都会接触这两种模式:饿汉式和饱汉式(懒汉式)。
那咱们先来看看这两个模式的实现。
饿汉式
定义一个私有的构造方法,并将自身的实例对象设置为一个私有属性,并加上static和final修饰符,而后经过公共的静态方法调用返回实例。
class SingletonTest1 { private SingletonTest1() { } private static final SingletonTest1 instance = new SingletonTest1(); public static SingletonTest1 getInstance() { return instance; } }
饱汉式
定义一个私有的构造方法,定义一个该类静态私有的变量,而后定义一个公共的静态方法,对该类的值进行空判断,不为空直接返回,不然从新构建一个。
class SingletonTest2 { private SingletonTest2() { } private static SingletonTest2 instance; public static SingletonTest2 getInstance() { if (instance == null) { instance = new SingletonTest2(); } return instance; } }
简单的介绍了这两种的模式,而后咱们再来看看这两种模式的优缺点吧。
饿汉式
饱汉式
虽然 饱汉式能够经过加上synchronized关键字保证线程安全。可是效率方法来讲还不说是最优。
这里在介绍下我的认为在JDK1.5以前最优的两种写法,一种是静态内部类,另外一种是双重锁检查。
静态内部类
定义一个私有的构造方法,定义一个该类私有静态的内部类,而后在内部类中定义一个该类的静态变量,而后经过公共的final修饰的静态方法调用返回实例。
class SingletonTest4 { private SingletonTest4(){ } private static class SingletonTest5{ private static SingletonTest4 instance = new SingletonTest4(); } public static final SingletonTest4 getInstance(){ return SingletonTest5.instance; } }
由于该类的内部类是私有的,除了对外公布的公共静态方法getInstance(),是没法访问的。由于它是延迟加载,因此读取读取实例的时候不会进行同步,几乎没有性能的缺陷,并且仍是线程安全的,而且不依赖JDK的版本。
双重锁检查
定义一个私有构造方法,经过volatile定义静态私有变量,保证了该变量的可见性,而后定义一个共有的静态方法,第一次对该对象实例化时与否判断,不为空直接返回,提高效率;而后使用synchronized 进行同步代码块,防止对象未初始化时,在多线程访问该对象在第一次建立后,再次重复的被建立;而后第二次对该对象实例化时与否判断,若是未初始化,则初始化,不然直接返回该实例。
class SingletonTest6 { private SingletonTest6() { } private static volatile SingletonTest6 instance; public static SingletonTest6 getIstance() { if (instance == null) { synchronized (SingletonTest6.class) { if (instance == null) { instance = new SingletonTest6(); } } } return instance; } }
这种模式在很长的一段时间内能够说是最优的了,内存占用低,效率高,线程安全,多线程操做原子性。可是有个缺点就是书写麻烦,对新手不太友好。
JDK1.5以后出现了枚举,而且完美支持单例模式,而且线程安全、效率高!可是这些不是最重要的,最重要的是书写超级简单!究竟有多简单,看下面的示例应该就能够了解一下了。。。
枚举单例
enum SingletonTest7{ INSTANCE; }
对的,你没看错,就这点代码,其它不须要了。。。
枚举须要在JDK1.5以后的版本,它无偿提供序列化机制,绝对防止屡次实例化,即便在面对复杂的序列化或者反射攻击的时候。这种方法也被Effective Java做者Josh Bloch 所提倡。
单例模式的几种使用就到这了,那么咱们来总结下使用单例模式须要注意什么(不包括枚举)。
原创不易,若是感受不错,但愿给个推荐!您的支持是我写做的最大动力!
版权声明:
做者:虚无境
博客园出处:http://www.cnblogs.com/xuwujing
CSDN出处:http://blog.csdn.net/qazwsxpcm
我的博客出处:http://www.panchengming.com